From 275e260a6cd4a8e506ba974feb85ebcd926c1739 Mon Sep 17 00:00:00 2001 From: Ryan Harrison Date: Mon, 18 Sep 2017 14:23:18 -0400 Subject: Convert string class names Automated using git grep & sed. Replace StringC classes with StringView classes. Remove the CFX_ prefix and put string classes in fxcrt namespace. Change AsStringC() to AsStringView(). Rename tests from TEST(fxcrt, *String*Foo) to TEST(*String*, Foo). Couple of tests needed to have their names regularlized. BUG=pdfium:894 Change-Id: I7ca038685c8d803795f3ed02545124f7a224c83d Reviewed-on: https://pdfium-review.googlesource.com/14151 Reviewed-by: Tom Sepez Commit-Queue: Ryan Harrison --- core/fxcrt/bytestring.cpp | 778 ++++++++++ core/fxcrt/bytestring.h | 279 ++++ core/fxcrt/bytestring_unittest.cpp | 1642 ++++++++++++++++++++ core/fxcrt/cfx_binarybuf.h | 2 +- core/fxcrt/cfx_blockbuffer.cpp | 10 +- core/fxcrt/cfx_blockbuffer.h | 2 +- core/fxcrt/cfx_bytestring.cpp | 780 ---------- core/fxcrt/cfx_bytestring.h | 273 ---- core/fxcrt/cfx_bytestring_unittest.cpp | 1642 -------------------- core/fxcrt/cfx_checksumcontext.cpp | 4 +- core/fxcrt/cfx_checksumcontext.h | 6 +- core/fxcrt/cfx_crtfileaccess.cpp | 2 +- core/fxcrt/cfx_crtfileaccess.h | 4 +- core/fxcrt/cfx_decimal.cpp | 8 +- core/fxcrt/cfx_decimal.h | 4 +- core/fxcrt/cfx_fileaccess_posix.cpp | 6 +- core/fxcrt/cfx_fileaccess_posix.h | 4 +- core/fxcrt/cfx_fileaccess_windows.cpp | 4 +- core/fxcrt/cfx_fileaccess_windows.h | 4 +- core/fxcrt/cfx_seekablestreamproxy.cpp | 2 +- core/fxcrt/cfx_seekablestreamproxy.h | 2 +- core/fxcrt/cfx_string_c_template.h | 240 --- core/fxcrt/cfx_string_pool_template.h | 8 +- core/fxcrt/cfx_string_pool_template_unittest.cpp | 52 +- core/fxcrt/cfx_utf8decoder.h | 2 +- core/fxcrt/cfx_widestring.cpp | 1055 ------------- core/fxcrt/cfx_widestring.h | 276 ---- core/fxcrt/cfx_widestring_unittest.cpp | 1605 ------------------- core/fxcrt/cfx_widetextbuf.cpp | 4 +- core/fxcrt/cfx_widetextbuf.h | 16 +- core/fxcrt/css/cfx_csscomputedstyle.cpp | 6 +- core/fxcrt/css/cfx_csscomputedstyle.h | 5 +- core/fxcrt/css/cfx_csscustomproperty.cpp | 4 +- core/fxcrt/css/cfx_csscustomproperty.h | 11 +- core/fxcrt/css/cfx_cssdatatable.cpp | 2 +- core/fxcrt/css/cfx_cssdatatable.h | 2 +- core/fxcrt/css/cfx_cssdeclaration.cpp | 32 +- core/fxcrt/css/cfx_cssdeclaration.h | 4 +- core/fxcrt/css/cfx_cssrulecollection.cpp | 2 +- core/fxcrt/css/cfx_cssrulecollection.h | 2 +- core/fxcrt/css/cfx_cssselector.cpp | 4 +- core/fxcrt/css/cfx_cssselector.h | 3 +- core/fxcrt/css/cfx_cssstringvalue.cpp | 2 +- core/fxcrt/css/cfx_cssstringvalue.h | 6 +- core/fxcrt/css/cfx_cssstyleselector.cpp | 22 +- core/fxcrt/css/cfx_cssstyleselector.h | 11 +- core/fxcrt/css/cfx_cssstylesheet.cpp | 12 +- core/fxcrt/css/cfx_cssstylesheet_unittest.cpp | 4 +- core/fxcrt/css/cfx_csssyntaxparser.cpp | 4 +- core/fxcrt/css/cfx_csssyntaxparser.h | 2 +- core/fxcrt/css/cfx_cssvaluelistparser_unittest.cpp | 40 +- core/fxcrt/fx_bidi.cpp | 2 +- core/fxcrt/fx_bidi.h | 4 +- core/fxcrt/fx_extension.cpp | 4 +- core/fxcrt/fx_stream.cpp | 10 +- core/fxcrt/fx_stream.h | 8 +- core/fxcrt/fx_string.cpp | 14 +- core/fxcrt/fx_string.h | 12 +- core/fxcrt/ifx_fileaccess.h | 4 +- core/fxcrt/ifx_locale.h | 20 +- core/fxcrt/string_view_template.h | 247 +++ core/fxcrt/widestring.cpp | 1054 +++++++++++++ core/fxcrt/widestring.h | 277 ++++ core/fxcrt/widestring_unittest.cpp | 1605 +++++++++++++++++++ core/fxcrt/xml/cfx_saxcontext.h | 2 +- core/fxcrt/xml/cfx_saxreader.cpp | 18 +- core/fxcrt/xml/cfx_saxreader.h | 12 +- core/fxcrt/xml/cfx_saxreader_unittest.cpp | 12 +- core/fxcrt/xml/cfx_saxreaderhandler.cpp | 16 +- core/fxcrt/xml/cfx_saxreaderhandler.h | 12 +- core/fxcrt/xml/cfx_xmlattributenode.cpp | 15 +- core/fxcrt/xml/cfx_xmlattributenode.h | 20 +- core/fxcrt/xml/cfx_xmlchardata.cpp | 2 +- core/fxcrt/xml/cfx_xmlchardata.h | 2 +- core/fxcrt/xml/cfx_xmldoc.cpp | 34 +- core/fxcrt/xml/cfx_xmlelement.cpp | 22 +- core/fxcrt/xml/cfx_xmlelement.h | 12 +- core/fxcrt/xml/cfx_xmlinstruction.cpp | 4 +- core/fxcrt/xml/cfx_xmlinstruction.h | 10 +- core/fxcrt/xml/cfx_xmlnode.cpp | 38 +- core/fxcrt/xml/cfx_xmlparser.cpp | 2 +- core/fxcrt/xml/cfx_xmlparser.h | 4 +- core/fxcrt/xml/cfx_xmlsyntaxparser.cpp | 2 +- core/fxcrt/xml/cfx_xmlsyntaxparser.h | 12 +- core/fxcrt/xml/cfx_xmltext.cpp | 2 +- core/fxcrt/xml/cfx_xmltext.h | 8 +- core/fxcrt/xml/cxml_attritem.cpp | 4 +- core/fxcrt/xml/cxml_attritem.h | 8 +- core/fxcrt/xml/cxml_attrmap.cpp | 12 +- core/fxcrt/xml/cxml_attrmap.h | 10 +- core/fxcrt/xml/cxml_content.cpp | 2 +- core/fxcrt/xml/cxml_content.h | 4 +- core/fxcrt/xml/cxml_element.cpp | 95 +- core/fxcrt/xml/cxml_element.h | 75 +- core/fxcrt/xml/cxml_parser.cpp | 47 +- core/fxcrt/xml/cxml_parser.h | 18 +- 96 files changed, 6347 insertions(+), 6346 deletions(-) create mode 100644 core/fxcrt/bytestring.cpp create mode 100644 core/fxcrt/bytestring.h create mode 100644 core/fxcrt/bytestring_unittest.cpp delete mode 100644 core/fxcrt/cfx_bytestring.cpp delete mode 100644 core/fxcrt/cfx_bytestring.h delete mode 100644 core/fxcrt/cfx_bytestring_unittest.cpp delete mode 100644 core/fxcrt/cfx_string_c_template.h delete mode 100644 core/fxcrt/cfx_widestring.cpp delete mode 100644 core/fxcrt/cfx_widestring.h delete mode 100644 core/fxcrt/cfx_widestring_unittest.cpp create mode 100644 core/fxcrt/string_view_template.h create mode 100644 core/fxcrt/widestring.cpp create mode 100644 core/fxcrt/widestring.h create mode 100644 core/fxcrt/widestring_unittest.cpp (limited to 'core/fxcrt') diff --git a/core/fxcrt/bytestring.cpp b/core/fxcrt/bytestring.cpp new file mode 100644 index 0000000000..dd4dbd99e2 --- /dev/null +++ b/core/fxcrt/bytestring.cpp @@ -0,0 +1,778 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "core/fxcrt/bytestring.h" + +#include + +#include +#include +#include + +#include "core/fxcrt/cfx_string_pool_template.h" +#include "core/fxcrt/cfx_utf8decoder.h" +#include "core/fxcrt/fx_codepage.h" +#include "core/fxcrt/fx_extension.h" +#include "core/fxcrt/fx_safe_types.h" +#include "third_party/base/numerics/safe_math.h" +#include "third_party/base/stl_util.h" + +template class CFX_StringDataTemplate; +template class fxcrt::StringViewTemplate; +template class CFX_StringPoolTemplate; +template struct std::hash; + +namespace { + +const char* FX_strstr(const char* haystack, + int haystack_len, + const char* needle, + int needle_len) { + if (needle_len > haystack_len || needle_len == 0) { + return nullptr; + } + const char* end_ptr = haystack + haystack_len - needle_len; + while (haystack <= end_ptr) { + int i = 0; + while (1) { + if (haystack[i] != needle[i]) { + break; + } + i++; + if (i == needle_len) { + return haystack; + } + } + haystack++; + } + return nullptr; +} + +#ifndef NDEBUG +bool IsValidCodePage(uint16_t codepage) { + switch (codepage) { + case FX_CODEPAGE_DefANSI: + case FX_CODEPAGE_ShiftJIS: + case FX_CODEPAGE_ChineseSimplified: + case FX_CODEPAGE_Hangul: + case FX_CODEPAGE_ChineseTraditional: + return true; + default: + return false; + } +} +#endif + +ByteString GetByteString(uint16_t codepage, const WideStringView& wstr) { + ASSERT(IsValidCodePage(codepage)); + + int src_len = wstr.GetLength(); + int dest_len = + FXSYS_WideCharToMultiByte(codepage, 0, wstr.unterminated_c_str(), src_len, + nullptr, 0, nullptr, nullptr); + if (!dest_len) + return ByteString(); + + ByteString bstr; + char* dest_buf = bstr.GetBuffer(dest_len); + FXSYS_WideCharToMultiByte(codepage, 0, wstr.unterminated_c_str(), src_len, + dest_buf, dest_len, nullptr, nullptr); + bstr.ReleaseBuffer(dest_len); + return bstr; +} + +} // namespace + +namespace fxcrt { + +static_assert(sizeof(ByteString) <= sizeof(char*), + "Strings must not require more space than pointers"); + +ByteString::ByteString(const char* pStr, FX_STRSIZE nLen) { + if (nLen) + m_pData.Reset(StringData::Create(pStr, nLen)); +} + +ByteString::ByteString(const uint8_t* pStr, FX_STRSIZE nLen) { + if (nLen) + m_pData.Reset( + StringData::Create(reinterpret_cast(pStr), nLen)); +} + +ByteString::ByteString() {} + +ByteString::ByteString(const ByteString& other) : m_pData(other.m_pData) {} + +ByteString::ByteString(ByteString&& other) noexcept { + m_pData.Swap(other.m_pData); +} + +ByteString::ByteString(char ch) { + m_pData.Reset(StringData::Create(1)); + m_pData->m_String[0] = ch; +} + +ByteString::ByteString(const char* ptr) + : ByteString(ptr, ptr ? FXSYS_strlen(ptr) : 0) {} + +ByteString::ByteString(const ByteStringView& stringSrc) { + if (!stringSrc.IsEmpty()) + m_pData.Reset(StringData::Create(stringSrc.unterminated_c_str(), + stringSrc.GetLength())); +} + +ByteString::ByteString(const ByteStringView& str1, const ByteStringView& str2) { + FX_SAFE_STRSIZE nSafeLen = str1.GetLength(); + nSafeLen += str2.GetLength(); + + FX_STRSIZE nNewLen = nSafeLen.ValueOrDie(); + if (nNewLen == 0) + return; + + m_pData.Reset(StringData::Create(nNewLen)); + m_pData->CopyContents(str1.unterminated_c_str(), str1.GetLength()); + m_pData->CopyContentsAt(str1.GetLength(), str2.unterminated_c_str(), + str2.GetLength()); +} + +ByteString::ByteString(const std::initializer_list& list) { + FX_SAFE_STRSIZE nSafeLen = 0; + for (const auto& item : list) + nSafeLen += item.GetLength(); + + FX_STRSIZE nNewLen = nSafeLen.ValueOrDie(); + if (nNewLen == 0) + return; + + m_pData.Reset(StringData::Create(nNewLen)); + + FX_STRSIZE nOffset = 0; + for (const auto& item : list) { + m_pData->CopyContentsAt(nOffset, item.unterminated_c_str(), + item.GetLength()); + nOffset += item.GetLength(); + } +} + +ByteString::ByteString(const std::ostringstream& outStream) { + std::string str = outStream.str(); + if (str.length() > 0) + m_pData.Reset(StringData::Create(str.c_str(), str.length())); +} + +ByteString::~ByteString() {} + +const ByteString& ByteString::operator=(const char* pStr) { + if (!pStr || !pStr[0]) + clear(); + else + AssignCopy(pStr, FXSYS_strlen(pStr)); + + return *this; +} + +const ByteString& ByteString::operator=(const ByteStringView& stringSrc) { + if (stringSrc.IsEmpty()) + clear(); + else + AssignCopy(stringSrc.unterminated_c_str(), stringSrc.GetLength()); + + return *this; +} + +const ByteString& ByteString::operator=(const ByteString& stringSrc) { + if (m_pData != stringSrc.m_pData) + m_pData = stringSrc.m_pData; + + return *this; +} + +const ByteString& ByteString::operator+=(const char* pStr) { + if (pStr) + Concat(pStr, FXSYS_strlen(pStr)); + + return *this; +} + +const ByteString& ByteString::operator+=(char ch) { + Concat(&ch, 1); + return *this; +} + +const ByteString& ByteString::operator+=(const ByteString& str) { + if (str.m_pData) + Concat(str.m_pData->m_String, str.m_pData->m_nDataLength); + + return *this; +} + +const ByteString& ByteString::operator+=(const ByteStringView& str) { + if (!str.IsEmpty()) + Concat(str.unterminated_c_str(), str.GetLength()); + + return *this; +} + +bool ByteString::operator==(const char* ptr) const { + if (!m_pData) + return !ptr || !ptr[0]; + + if (!ptr) + return m_pData->m_nDataLength == 0; + + return FXSYS_strlen(ptr) == m_pData->m_nDataLength && + memcmp(ptr, m_pData->m_String, m_pData->m_nDataLength) == 0; +} + +bool ByteString::operator==(const ByteStringView& str) const { + if (!m_pData) + return str.IsEmpty(); + + return m_pData->m_nDataLength == str.GetLength() && + memcmp(m_pData->m_String, str.unterminated_c_str(), str.GetLength()) == + 0; +} + +bool ByteString::operator==(const ByteString& other) const { + if (m_pData == other.m_pData) + return true; + + if (IsEmpty()) + return other.IsEmpty(); + + if (other.IsEmpty()) + return false; + + return other.m_pData->m_nDataLength == m_pData->m_nDataLength && + memcmp(other.m_pData->m_String, m_pData->m_String, + m_pData->m_nDataLength) == 0; +} + +bool ByteString::operator<(const ByteString& str) const { + if (m_pData == str.m_pData) + return false; + + int result = + memcmp(c_str(), str.c_str(), std::min(GetLength(), str.GetLength())); + return result < 0 || (result == 0 && GetLength() < str.GetLength()); +} + +bool ByteString::EqualNoCase(const ByteStringView& str) const { + if (!m_pData) + return str.IsEmpty(); + + FX_STRSIZE len = str.GetLength(); + if (m_pData->m_nDataLength != len) + return false; + + const uint8_t* pThis = (const uint8_t*)m_pData->m_String; + const uint8_t* pThat = str.raw_str(); + for (FX_STRSIZE i = 0; i < len; i++) { + if ((*pThis) != (*pThat)) { + uint8_t bThis = FXSYS_tolower(*pThis); + uint8_t bThat = FXSYS_tolower(*pThat); + if (bThis != bThat) + return false; + } + pThis++; + pThat++; + } + return true; +} + +void ByteString::AssignCopy(const char* pSrcData, FX_STRSIZE nSrcLen) { + AllocBeforeWrite(nSrcLen); + m_pData->CopyContents(pSrcData, nSrcLen); + m_pData->m_nDataLength = nSrcLen; +} + +void ByteString::ReallocBeforeWrite(FX_STRSIZE nNewLength) { + if (m_pData && m_pData->CanOperateInPlace(nNewLength)) + return; + + if (nNewLength == 0) { + clear(); + return; + } + + CFX_RetainPtr pNewData(StringData::Create(nNewLength)); + if (m_pData) { + FX_STRSIZE nCopyLength = std::min(m_pData->m_nDataLength, nNewLength); + pNewData->CopyContents(m_pData->m_String, nCopyLength); + pNewData->m_nDataLength = nCopyLength; + } else { + pNewData->m_nDataLength = 0; + } + pNewData->m_String[pNewData->m_nDataLength] = 0; + m_pData.Swap(pNewData); +} + +void ByteString::AllocBeforeWrite(FX_STRSIZE nNewLength) { + if (m_pData && m_pData->CanOperateInPlace(nNewLength)) + return; + + if (nNewLength == 0) { + clear(); + return; + } + + m_pData.Reset(StringData::Create(nNewLength)); +} + +void ByteString::ReleaseBuffer(FX_STRSIZE nNewLength) { + if (!m_pData) + return; + + nNewLength = std::min(nNewLength, m_pData->m_nAllocLength); + if (nNewLength == 0) { + clear(); + return; + } + + ASSERT(m_pData->m_nRefs == 1); + m_pData->m_nDataLength = nNewLength; + m_pData->m_String[nNewLength] = 0; + if (m_pData->m_nAllocLength - nNewLength >= 32) { + // Over arbitrary threshold, so pay the price to relocate. Force copy to + // always occur by holding a second reference to the string. + ByteString preserve(*this); + ReallocBeforeWrite(nNewLength); + } +} + +void ByteString::Reserve(FX_STRSIZE len) { + GetBuffer(len); +} + +char* ByteString::GetBuffer(FX_STRSIZE nMinBufLength) { + if (!m_pData) { + if (nMinBufLength == 0) + return nullptr; + + m_pData.Reset(StringData::Create(nMinBufLength)); + m_pData->m_nDataLength = 0; + m_pData->m_String[0] = 0; + return m_pData->m_String; + } + + if (m_pData->CanOperateInPlace(nMinBufLength)) + return m_pData->m_String; + + nMinBufLength = std::max(nMinBufLength, m_pData->m_nDataLength); + if (nMinBufLength == 0) + return nullptr; + + CFX_RetainPtr pNewData(StringData::Create(nMinBufLength)); + pNewData->CopyContents(*m_pData); + pNewData->m_nDataLength = m_pData->m_nDataLength; + m_pData.Swap(pNewData); + return m_pData->m_String; +} + +FX_STRSIZE ByteString::Delete(FX_STRSIZE index, FX_STRSIZE count) { + if (!m_pData) + return 0; + + FX_STRSIZE old_length = m_pData->m_nDataLength; + if (count == 0 || + index != pdfium::clamp(index, static_cast(0), old_length)) + return old_length; + + FX_STRSIZE removal_length = index + count; + if (removal_length > old_length) + return old_length; + + ReallocBeforeWrite(old_length); + FX_STRSIZE chars_to_copy = old_length - removal_length + 1; + memmove(m_pData->m_String + index, m_pData->m_String + removal_length, + chars_to_copy); + m_pData->m_nDataLength = old_length - count; + return m_pData->m_nDataLength; +} + +void ByteString::Concat(const char* pSrcData, FX_STRSIZE nSrcLen) { + if (!pSrcData || nSrcLen == 0) + return; + + if (!m_pData) { + m_pData.Reset(StringData::Create(pSrcData, nSrcLen)); + return; + } + + if (m_pData->CanOperateInPlace(m_pData->m_nDataLength + nSrcLen)) { + m_pData->CopyContentsAt(m_pData->m_nDataLength, pSrcData, nSrcLen); + m_pData->m_nDataLength += nSrcLen; + return; + } + + CFX_RetainPtr pNewData( + StringData::Create(m_pData->m_nDataLength + nSrcLen)); + pNewData->CopyContents(*m_pData); + pNewData->CopyContentsAt(m_pData->m_nDataLength, pSrcData, nSrcLen); + m_pData.Swap(pNewData); +} + +ByteString ByteString::Mid(FX_STRSIZE first, FX_STRSIZE count) const { + if (!m_pData) + return ByteString(); + + if (!IsValidIndex(first)) + return ByteString(); + + if (count == 0 || !IsValidLength(count)) + return ByteString(); + + if (!IsValidIndex(first + count - 1)) + return ByteString(); + + if (first == 0 && count == m_pData->m_nDataLength) + return *this; + + ByteString dest; + AllocCopy(dest, count, first); + return dest; +} + +ByteString ByteString::Left(FX_STRSIZE count) const { + if (count == 0 || !IsValidLength(count)) + return ByteString(); + return Mid(0, count); +} + +ByteString ByteString::Right(FX_STRSIZE count) const { + if (count == 0 || !IsValidLength(count)) + return ByteString(); + return Mid(GetLength() - count, count); +} + +void ByteString::AllocCopy(ByteString& dest, + FX_STRSIZE nCopyLen, + FX_STRSIZE nCopyIndex) const { + if (nCopyLen == 0) + return; + + CFX_RetainPtr pNewData( + StringData::Create(m_pData->m_String + nCopyIndex, nCopyLen)); + dest.m_pData.Swap(pNewData); +} + +#define FORCE_ANSI 0x10000 +#define FORCE_UNICODE 0x20000 +#define FORCE_INT64 0x40000 + +ByteString ByteString::FormatInteger(int i) { + char buf[32]; + FXSYS_snprintf(buf, 32, "%d", i); + return ByteString(buf); +} + +void ByteString::FormatV(const char* pFormat, va_list argList) { + va_list argListCopy; + va_copy(argListCopy, argList); + FX_STRSIZE nMaxLen = vsnprintf(nullptr, 0, pFormat, argListCopy); + va_end(argListCopy); + if (nMaxLen > 0) { + GetBuffer(nMaxLen); + if (m_pData) { + // In the following two calls, there's always space in the buffer for + // a terminating NUL that's not included in nMaxLen. + memset(m_pData->m_String, 0, nMaxLen + 1); + va_copy(argListCopy, argList); + vsnprintf(m_pData->m_String, nMaxLen + 1, pFormat, argListCopy); + va_end(argListCopy); + ReleaseBuffer(GetStringLength()); + } + } +} + +void ByteString::Format(const char* pFormat, ...) { + va_list argList; + va_start(argList, pFormat); + FormatV(pFormat, argList); + va_end(argList); +} + +void ByteString::SetAt(FX_STRSIZE index, char c) { + ASSERT(IsValidIndex(index)); + ReallocBeforeWrite(m_pData->m_nDataLength); + m_pData->m_String[index] = c; +} + +FX_STRSIZE ByteString::Insert(FX_STRSIZE location, char ch) { + const FX_STRSIZE cur_length = m_pData ? m_pData->m_nDataLength : 0; + if (!IsValidLength(location)) + return cur_length; + + const FX_STRSIZE new_length = cur_length + 1; + ReallocBeforeWrite(new_length); + memmove(m_pData->m_String + location + 1, m_pData->m_String + location, + new_length - location); + m_pData->m_String[location] = ch; + m_pData->m_nDataLength = new_length; + return new_length; +} + +pdfium::Optional ByteString::Find(char ch, FX_STRSIZE start) const { + if (!m_pData) + return pdfium::Optional(); + + if (!IsValidIndex(start)) + return pdfium::Optional(); + + const char* pStr = static_cast( + memchr(m_pData->m_String + start, ch, m_pData->m_nDataLength - start)); + return pStr ? pdfium::Optional( + static_cast(pStr - m_pData->m_String)) + : pdfium::Optional(); +} + +pdfium::Optional ByteString::Find(const ByteStringView& subStr, + FX_STRSIZE start) const { + if (!m_pData) + return pdfium::Optional(); + + if (!IsValidIndex(start)) + return pdfium::Optional(); + + const char* pStr = + FX_strstr(m_pData->m_String + start, m_pData->m_nDataLength - start, + subStr.unterminated_c_str(), subStr.GetLength()); + return pStr ? pdfium::Optional( + static_cast(pStr - m_pData->m_String)) + : pdfium::Optional(); +} + +pdfium::Optional ByteString::ReverseFind(char ch) const { + if (!m_pData) + return pdfium::Optional(); + + FX_STRSIZE nLength = m_pData->m_nDataLength; + while (nLength--) { + if (m_pData->m_String[nLength] == ch) + return pdfium::Optional(nLength); + } + return pdfium::Optional(); +} + +void ByteString::MakeLower() { + if (!m_pData) + return; + + ReallocBeforeWrite(m_pData->m_nDataLength); + FXSYS_strlwr(m_pData->m_String); +} + +void ByteString::MakeUpper() { + if (!m_pData) + return; + + ReallocBeforeWrite(m_pData->m_nDataLength); + FXSYS_strupr(m_pData->m_String); +} + +FX_STRSIZE ByteString::Remove(char chRemove) { + if (!m_pData || m_pData->m_nDataLength < 1) + return 0; + + char* pstrSource = m_pData->m_String; + char* pstrEnd = m_pData->m_String + m_pData->m_nDataLength; + while (pstrSource < pstrEnd) { + if (*pstrSource == chRemove) + break; + pstrSource++; + } + if (pstrSource == pstrEnd) + return 0; + + ptrdiff_t copied = pstrSource - m_pData->m_String; + ReallocBeforeWrite(m_pData->m_nDataLength); + pstrSource = m_pData->m_String + copied; + pstrEnd = m_pData->m_String + m_pData->m_nDataLength; + + char* pstrDest = pstrSource; + while (pstrSource < pstrEnd) { + if (*pstrSource != chRemove) { + *pstrDest = *pstrSource; + pstrDest++; + } + pstrSource++; + } + + *pstrDest = 0; + FX_STRSIZE nCount = static_cast(pstrSource - pstrDest); + m_pData->m_nDataLength -= nCount; + return nCount; +} + +FX_STRSIZE ByteString::Replace(const ByteStringView& pOld, + const ByteStringView& pNew) { + if (!m_pData || pOld.IsEmpty()) + return 0; + + FX_STRSIZE nSourceLen = pOld.GetLength(); + FX_STRSIZE nReplacementLen = pNew.GetLength(); + FX_STRSIZE nCount = 0; + const char* pStart = m_pData->m_String; + char* pEnd = m_pData->m_String + m_pData->m_nDataLength; + while (1) { + const char* pTarget = FX_strstr(pStart, static_cast(pEnd - pStart), + pOld.unterminated_c_str(), nSourceLen); + if (!pTarget) + break; + + nCount++; + pStart = pTarget + nSourceLen; + } + if (nCount == 0) + return 0; + + FX_STRSIZE nNewLength = + m_pData->m_nDataLength + (nReplacementLen - nSourceLen) * nCount; + + if (nNewLength == 0) { + clear(); + return nCount; + } + + CFX_RetainPtr pNewData(StringData::Create(nNewLength)); + pStart = m_pData->m_String; + char* pDest = pNewData->m_String; + for (FX_STRSIZE i = 0; i < nCount; i++) { + const char* pTarget = FX_strstr(pStart, static_cast(pEnd - pStart), + pOld.unterminated_c_str(), nSourceLen); + memcpy(pDest, pStart, pTarget - pStart); + pDest += pTarget - pStart; + memcpy(pDest, pNew.unterminated_c_str(), pNew.GetLength()); + pDest += pNew.GetLength(); + pStart = pTarget + nSourceLen; + } + memcpy(pDest, pStart, pEnd - pStart); + m_pData.Swap(pNewData); + return nCount; +} + +WideString ByteString::UTF8Decode() const { + CFX_UTF8Decoder decoder; + for (FX_STRSIZE i = 0; i < GetLength(); i++) { + decoder.Input(static_cast(m_pData->m_String[i])); + } + return WideString(decoder.GetResult()); +} + +// static +ByteString ByteString::FromUnicode(const WideString& str) { + return GetByteString(0, str.AsStringView()); +} + +int ByteString::Compare(const ByteStringView& str) const { + if (!m_pData) { + return str.IsEmpty() ? 0 : -1; + } + FX_STRSIZE this_len = m_pData->m_nDataLength; + FX_STRSIZE that_len = str.GetLength(); + FX_STRSIZE min_len = std::min(this_len, that_len); + for (FX_STRSIZE i = 0; i < min_len; i++) { + if (static_cast(m_pData->m_String[i]) < str[i]) { + return -1; + } + if (static_cast(m_pData->m_String[i]) > str[i]) { + return 1; + } + } + if (this_len < that_len) { + return -1; + } + if (this_len > that_len) { + return 1; + } + return 0; +} + +void ByteString::TrimRight(const ByteStringView& pTargets) { + if (!m_pData || pTargets.IsEmpty()) + return; + + FX_STRSIZE pos = GetLength(); + if (pos == 0) + return; + + while (pos) { + FX_STRSIZE i = 0; + while (i < pTargets.GetLength() && + pTargets[i] != m_pData->m_String[pos - 1]) { + i++; + } + if (i == pTargets.GetLength()) { + break; + } + pos--; + } + if (pos < m_pData->m_nDataLength) { + ReallocBeforeWrite(m_pData->m_nDataLength); + m_pData->m_String[pos] = 0; + m_pData->m_nDataLength = pos; + } +} + +void ByteString::TrimRight(char chTarget) { + TrimRight(ByteStringView(chTarget)); +} + +void ByteString::TrimRight() { + TrimRight("\x09\x0a\x0b\x0c\x0d\x20"); +} + +void ByteString::TrimLeft(const ByteStringView& pTargets) { + if (!m_pData || pTargets.IsEmpty()) + return; + + FX_STRSIZE len = GetLength(); + if (len == 0) + return; + + FX_STRSIZE pos = 0; + while (pos < len) { + FX_STRSIZE i = 0; + while (i < pTargets.GetLength() && pTargets[i] != m_pData->m_String[pos]) { + i++; + } + if (i == pTargets.GetLength()) { + break; + } + pos++; + } + if (pos) { + ReallocBeforeWrite(len); + FX_STRSIZE nDataLength = len - pos; + memmove(m_pData->m_String, m_pData->m_String + pos, + (nDataLength + 1) * sizeof(char)); + m_pData->m_nDataLength = nDataLength; + } +} + +void ByteString::TrimLeft(char chTarget) { + TrimLeft(ByteStringView(chTarget)); +} + +void ByteString::TrimLeft() { + TrimLeft("\x09\x0a\x0b\x0c\x0d\x20"); +} + +ByteString ByteString::FormatFloat(float d, int precision) { + char buf[32]; + FX_STRSIZE len = FX_ftoa(d, buf); + return ByteString(buf, len); +} + +std::ostream& operator<<(std::ostream& os, const ByteString& str) { + return os.write(str.c_str(), str.GetLength()); +} + +std::ostream& operator<<(std::ostream& os, const ByteStringView& str) { + return os.write(str.unterminated_c_str(), str.GetLength()); +} + +} // namespace fxcrt diff --git a/core/fxcrt/bytestring.h b/core/fxcrt/bytestring.h new file mode 100644 index 0000000000..0220e707cd --- /dev/null +++ b/core/fxcrt/bytestring.h @@ -0,0 +1,279 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef CORE_FXCRT_BYTESTRING_H_ +#define CORE_FXCRT_BYTESTRING_H_ + +#include +#include +#include +#include + +#include "core/fxcrt/cfx_retain_ptr.h" +#include "core/fxcrt/cfx_string_data_template.h" +#include "core/fxcrt/fx_system.h" +#include "core/fxcrt/string_view_template.h" +#include "third_party/base/optional.h" + +class ByteString_Concat_Test; +class fxcrt_ByteStringPool_Test; + +namespace fxcrt { + +class WideString; + +// A mutable string with shared buffers using copy-on-write semantics that +// avoids the cost of std::string's iterator stability guarantees. +class ByteString { + public: + using CharType = char; + using const_iterator = const CharType*; + using const_reverse_iterator = std::reverse_iterator; + + ByteString(); + ByteString(const ByteString& other); + ByteString(ByteString&& other) noexcept; + + // Deliberately implicit to avoid calling on every string literal. + // NOLINTNEXTLINE(runtime/explicit) + ByteString(char ch); + // NOLINTNEXTLINE(runtime/explicit) + ByteString(const char* ptr); + + // No implicit conversions from wide strings. + // NOLINTNEXTLINE(runtime/explicit) + ByteString(wchar_t) = delete; + + ByteString(const char* ptr, FX_STRSIZE len); + ByteString(const uint8_t* ptr, FX_STRSIZE len); + + explicit ByteString(const ByteStringView& bstrc); + ByteString(const ByteStringView& bstrc1, const ByteStringView& bstrc2); + ByteString(const std::initializer_list& list); + explicit ByteString(const std::ostringstream& outStream); + + ~ByteString(); + + void clear() { m_pData.Reset(); } + + static ByteString FromUnicode(const WideString& str); + + // Explicit conversion to C-style string. + // Note: Any subsequent modification of |this| will invalidate the result. + const char* c_str() const { return m_pData ? m_pData->m_String : ""; } + + // Explicit conversion to uint8_t*. + // Note: Any subsequent modification of |this| will invalidate the result. + const uint8_t* raw_str() const { + return m_pData ? reinterpret_cast(m_pData->m_String) + : nullptr; + } + + // Explicit conversion to ByteStringView. + // Note: Any subsequent modification of |this| will invalidate the result. + ByteStringView AsStringView() const { + return ByteStringView(raw_str(), GetLength()); + } + + // Note: Any subsequent modification of |this| will invalidate iterators. + const_iterator begin() const { return m_pData ? m_pData->m_String : nullptr; } + const_iterator end() const { + return m_pData ? m_pData->m_String + m_pData->m_nDataLength : nullptr; + } + + // Note: Any subsequent modification of |this| will invalidate iterators. + const_reverse_iterator rbegin() const { + return const_reverse_iterator(end()); + } + const_reverse_iterator rend() const { + return const_reverse_iterator(begin()); + } + + FX_STRSIZE GetLength() const { return m_pData ? m_pData->m_nDataLength : 0; } + FX_STRSIZE GetStringLength() const { + return m_pData ? FXSYS_strlen(m_pData->m_String) : 0; + } + bool IsEmpty() const { return !GetLength(); } + bool IsValidIndex(FX_STRSIZE index) const { return index < GetLength(); } + bool IsValidLength(FX_STRSIZE length) const { return length <= GetLength(); } + + int Compare(const ByteStringView& str) const; + bool EqualNoCase(const ByteStringView& str) const; + + bool operator==(const char* ptr) const; + bool operator==(const ByteStringView& str) const; + bool operator==(const ByteString& other) const; + + bool operator!=(const char* ptr) const { return !(*this == ptr); } + bool operator!=(const ByteStringView& str) const { return !(*this == str); } + bool operator!=(const ByteString& other) const { return !(*this == other); } + + bool operator<(const ByteString& str) const; + + const ByteString& operator=(const char* str); + const ByteString& operator=(const ByteStringView& bstrc); + const ByteString& operator=(const ByteString& stringSrc); + + const ByteString& operator+=(char ch); + const ByteString& operator+=(const char* str); + const ByteString& operator+=(const ByteString& str); + const ByteString& operator+=(const ByteStringView& bstrc); + + CharType operator[](const FX_STRSIZE index) const { + ASSERT(IsValidIndex(index)); + return m_pData ? m_pData->m_String[index] : 0; + } + + CharType First() const { return GetLength() ? (*this)[0] : 0; } + CharType Last() const { return GetLength() ? (*this)[GetLength() - 1] : 0; } + + void SetAt(FX_STRSIZE index, char c); + + FX_STRSIZE Insert(FX_STRSIZE index, char ch); + FX_STRSIZE InsertAtFront(char ch) { return Insert(0, ch); } + FX_STRSIZE InsertAtBack(char ch) { return Insert(GetLength(), ch); } + FX_STRSIZE Delete(FX_STRSIZE index, FX_STRSIZE count = 1); + + void Format(const char* lpszFormat, ...); + void FormatV(const char* lpszFormat, va_list argList); + + void Reserve(FX_STRSIZE len); + char* GetBuffer(FX_STRSIZE len); + void ReleaseBuffer(FX_STRSIZE len); + + ByteString Mid(FX_STRSIZE first, FX_STRSIZE count) const; + ByteString Left(FX_STRSIZE count) const; + ByteString Right(FX_STRSIZE count) const; + + pdfium::Optional Find(const ByteStringView& lpszSub, + FX_STRSIZE start = 0) const; + pdfium::Optional Find(char ch, FX_STRSIZE start = 0) const; + pdfium::Optional ReverseFind(char ch) const; + + bool Contains(const ByteStringView& lpszSub, FX_STRSIZE start = 0) const { + return Find(lpszSub, start).has_value(); + } + + bool Contains(char ch, FX_STRSIZE start = 0) const { + return Find(ch, start).has_value(); + } + + void MakeLower(); + void MakeUpper(); + + void TrimRight(); + void TrimRight(char chTarget); + void TrimRight(const ByteStringView& lpszTargets); + + void TrimLeft(); + void TrimLeft(char chTarget); + void TrimLeft(const ByteStringView& lpszTargets); + + FX_STRSIZE Replace(const ByteStringView& lpszOld, + const ByteStringView& lpszNew); + + FX_STRSIZE Remove(char ch); + + WideString UTF8Decode() const; + + uint32_t GetID() const { return AsStringView().GetID(); } + + static ByteString FormatInteger(int i); + static ByteString FormatFloat(float f, int precision = 0); + + protected: + using StringData = CFX_StringDataTemplate; + + void ReallocBeforeWrite(FX_STRSIZE nNewLen); + void AllocBeforeWrite(FX_STRSIZE nNewLen); + void AllocCopy(ByteString& dest, + FX_STRSIZE nCopyLen, + FX_STRSIZE nCopyIndex) const; + void AssignCopy(const char* pSrcData, FX_STRSIZE nSrcLen); + void Concat(const char* lpszSrcData, FX_STRSIZE nSrcLen); + + CFX_RetainPtr m_pData; + + friend ByteString_Concat_Test; + friend fxcrt_ByteStringPool_Test; +}; + +inline bool operator==(const char* lhs, const ByteString& rhs) { + return rhs == lhs; +} +inline bool operator==(const ByteStringView& lhs, const ByteString& rhs) { + return rhs == lhs; +} +inline bool operator!=(const char* lhs, const ByteString& rhs) { + return rhs != lhs; +} +inline bool operator!=(const ByteStringView& lhs, const ByteString& rhs) { + return rhs != lhs; +} + +inline ByteString operator+(const ByteStringView& str1, + const ByteStringView& str2) { + return ByteString(str1, str2); +} +inline ByteString operator+(const ByteStringView& str1, const char* str2) { + return ByteString(str1, str2); +} +inline ByteString operator+(const char* str1, const ByteStringView& str2) { + return ByteString(str1, str2); +} +inline ByteString operator+(const ByteStringView& str1, char ch) { + return ByteString(str1, ByteStringView(ch)); +} +inline ByteString operator+(char ch, const ByteStringView& str2) { + return ByteString(ch, str2); +} +inline ByteString operator+(const ByteString& str1, const ByteString& str2) { + return ByteString(str1.AsStringView(), str2.AsStringView()); +} +inline ByteString operator+(const ByteString& str1, char ch) { + return ByteString(str1.AsStringView(), ByteStringView(ch)); +} +inline ByteString operator+(char ch, const ByteString& str2) { + return ByteString(ch, str2.AsStringView()); +} +inline ByteString operator+(const ByteString& str1, const char* str2) { + return ByteString(str1.AsStringView(), str2); +} +inline ByteString operator+(const char* str1, const ByteString& str2) { + return ByteString(str1, str2.AsStringView()); +} +inline ByteString operator+(const ByteString& str1, + const ByteStringView& str2) { + return ByteString(str1.AsStringView(), str2); +} +inline ByteString operator+(const ByteStringView& str1, + const ByteString& str2) { + return ByteString(str1, str2.AsStringView()); +} + +std::ostream& operator<<(std::ostream& os, const ByteString& str); +std::ostream& operator<<(std::ostream& os, const ByteStringView& str); + +} // namespace fxcrt + +using ByteString = fxcrt::ByteString; + +uint32_t FX_HashCode_GetA(const ByteStringView& str, bool bIgnoreCase); + +namespace std { + +template <> +struct hash { + std::size_t operator()(const ByteString& str) const { + return FX_HashCode_GetA(str.AsStringView(), false); + } +}; + +} // namespace std + +extern template struct std::hash; + +#endif // CORE_FXCRT_BYTESTRING_H_ diff --git a/core/fxcrt/bytestring_unittest.cpp b/core/fxcrt/bytestring_unittest.cpp new file mode 100644 index 0000000000..06ba1f42fd --- /dev/null +++ b/core/fxcrt/bytestring_unittest.cpp @@ -0,0 +1,1642 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "core/fxcrt/bytestring.h" + +#include +#include + +#include "core/fxcrt/fx_string.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/base/stl_util.h" + +TEST(ByteString, ElementAccess) { + const ByteString abc("abc"); + EXPECT_EQ('a', abc[0]); + EXPECT_EQ('b', abc[1]); + EXPECT_EQ('c', abc[2]); +#ifndef NDEBUG + EXPECT_DEATH({ abc[3]; }, ".*"); +#endif + + ByteString mutable_abc = abc; + EXPECT_EQ(abc.c_str(), mutable_abc.c_str()); + EXPECT_EQ('a', mutable_abc[0]); + EXPECT_EQ('b', mutable_abc[1]); + EXPECT_EQ('c', mutable_abc[2]); + EXPECT_EQ(abc.c_str(), mutable_abc.c_str()); + EXPECT_EQ("abc", abc); + + const char* c_str = abc.c_str(); + mutable_abc.SetAt(0, 'd'); + EXPECT_EQ(c_str, abc.c_str()); + EXPECT_NE(c_str, mutable_abc.c_str()); + EXPECT_EQ("abc", abc); + EXPECT_EQ("dbc", mutable_abc); + + mutable_abc.SetAt(1, 'e'); + EXPECT_EQ("abc", abc); + EXPECT_EQ("dec", mutable_abc); + + mutable_abc.SetAt(2, 'f'); + EXPECT_EQ("abc", abc); + EXPECT_EQ("def", mutable_abc); +#ifndef NDEBUG + EXPECT_DEATH({ mutable_abc.SetAt(3, 'g'); }, ".*"); + EXPECT_EQ("abc", abc); +#endif +} + +TEST(ByteString, OperatorLT) { + ByteString empty; + ByteString a("a"); + ByteString abc("abc"); + ByteString def("def"); + + EXPECT_FALSE(empty < empty); + EXPECT_FALSE(a < a); + EXPECT_FALSE(abc < abc); + EXPECT_FALSE(def < def); + + EXPECT_TRUE(empty < a); + EXPECT_FALSE(a < empty); + + EXPECT_TRUE(empty < abc); + EXPECT_FALSE(abc < empty); + + EXPECT_TRUE(empty < def); + EXPECT_FALSE(def < empty); + + EXPECT_TRUE(a < abc); + EXPECT_FALSE(abc < a); + + EXPECT_TRUE(a < def); + EXPECT_FALSE(def < a); + + EXPECT_TRUE(abc < def); + EXPECT_FALSE(def < abc); +} + +TEST(ByteString, OperatorEQ) { + ByteString null_string; + EXPECT_TRUE(null_string == null_string); + + ByteString empty_string(""); + EXPECT_TRUE(empty_string == empty_string); + EXPECT_TRUE(empty_string == null_string); + EXPECT_TRUE(null_string == empty_string); + + ByteString deleted_string("hello"); + deleted_string.Delete(0, 5); + EXPECT_TRUE(deleted_string == deleted_string); + EXPECT_TRUE(deleted_string == null_string); + EXPECT_TRUE(deleted_string == empty_string); + EXPECT_TRUE(null_string == deleted_string); + EXPECT_TRUE(empty_string == deleted_string); + + ByteString byte_string("hello"); + EXPECT_TRUE(byte_string == byte_string); + EXPECT_FALSE(byte_string == null_string); + EXPECT_FALSE(byte_string == empty_string); + EXPECT_FALSE(byte_string == deleted_string); + EXPECT_FALSE(null_string == byte_string); + EXPECT_FALSE(empty_string == byte_string); + EXPECT_FALSE(deleted_string == byte_string); + + ByteString byte_string_same1("hello"); + EXPECT_TRUE(byte_string == byte_string_same1); + EXPECT_TRUE(byte_string_same1 == byte_string); + + ByteString byte_string_same2(byte_string); + EXPECT_TRUE(byte_string == byte_string_same2); + EXPECT_TRUE(byte_string_same2 == byte_string); + + ByteString byte_string1("he"); + ByteString byte_string2("hellp"); + ByteString byte_string3("hellod"); + EXPECT_FALSE(byte_string == byte_string1); + EXPECT_FALSE(byte_string == byte_string2); + EXPECT_FALSE(byte_string == byte_string3); + EXPECT_FALSE(byte_string1 == byte_string); + EXPECT_FALSE(byte_string2 == byte_string); + EXPECT_FALSE(byte_string3 == byte_string); + + ByteStringView null_string_c; + ByteStringView empty_string_c(""); + EXPECT_TRUE(null_string == null_string_c); + EXPECT_TRUE(null_string == empty_string_c); + EXPECT_TRUE(empty_string == null_string_c); + EXPECT_TRUE(empty_string == empty_string_c); + EXPECT_TRUE(deleted_string == null_string_c); + EXPECT_TRUE(deleted_string == empty_string_c); + EXPECT_TRUE(null_string_c == null_string); + EXPECT_TRUE(empty_string_c == null_string); + EXPECT_TRUE(null_string_c == empty_string); + EXPECT_TRUE(empty_string_c == empty_string); + EXPECT_TRUE(null_string_c == deleted_string); + EXPECT_TRUE(empty_string_c == deleted_string); + + ByteStringView byte_string_c_same1("hello"); + EXPECT_TRUE(byte_string == byte_string_c_same1); + EXPECT_TRUE(byte_string_c_same1 == byte_string); + + ByteStringView byte_string_c1("he"); + ByteStringView byte_string_c2("hellp"); + ByteStringView byte_string_c3("hellod"); + EXPECT_FALSE(byte_string == byte_string_c1); + EXPECT_FALSE(byte_string == byte_string_c2); + EXPECT_FALSE(byte_string == byte_string_c3); + EXPECT_FALSE(byte_string_c1 == byte_string); + EXPECT_FALSE(byte_string_c2 == byte_string); + EXPECT_FALSE(byte_string_c3 == byte_string); + + const char* c_null_string = nullptr; + const char* c_empty_string = ""; + EXPECT_TRUE(null_string == c_null_string); + EXPECT_TRUE(null_string == c_empty_string); + EXPECT_TRUE(empty_string == c_null_string); + EXPECT_TRUE(empty_string == c_empty_string); + EXPECT_TRUE(deleted_string == c_null_string); + EXPECT_TRUE(deleted_string == c_empty_string); + EXPECT_TRUE(c_null_string == null_string); + EXPECT_TRUE(c_empty_string == null_string); + EXPECT_TRUE(c_null_string == empty_string); + EXPECT_TRUE(c_empty_string == empty_string); + EXPECT_TRUE(c_null_string == deleted_string); + EXPECT_TRUE(c_empty_string == deleted_string); + + const char* c_string_same1 = "hello"; + EXPECT_TRUE(byte_string == c_string_same1); + EXPECT_TRUE(c_string_same1 == byte_string); + + const char* c_string1 = "he"; + const char* c_string2 = "hellp"; + const char* c_string3 = "hellod"; + EXPECT_FALSE(byte_string == c_string1); + EXPECT_FALSE(byte_string == c_string2); + EXPECT_FALSE(byte_string == c_string3); + EXPECT_FALSE(c_string1 == byte_string); + EXPECT_FALSE(c_string2 == byte_string); + EXPECT_FALSE(c_string3 == byte_string); +} + +TEST(ByteString, OperatorNE) { + ByteString null_string; + EXPECT_FALSE(null_string != null_string); + + ByteString empty_string(""); + EXPECT_FALSE(empty_string != empty_string); + EXPECT_FALSE(empty_string != null_string); + EXPECT_FALSE(null_string != empty_string); + + ByteString deleted_string("hello"); + deleted_string.Delete(0, 5); + EXPECT_FALSE(deleted_string != deleted_string); + EXPECT_FALSE(deleted_string != null_string); + EXPECT_FALSE(deleted_string != empty_string); + EXPECT_FALSE(deleted_string != deleted_string); + EXPECT_FALSE(null_string != deleted_string); + EXPECT_FALSE(empty_string != deleted_string); + EXPECT_FALSE(deleted_string != deleted_string); + + ByteString byte_string("hello"); + EXPECT_FALSE(byte_string != byte_string); + EXPECT_TRUE(byte_string != null_string); + EXPECT_TRUE(byte_string != empty_string); + EXPECT_TRUE(byte_string != deleted_string); + EXPECT_TRUE(null_string != byte_string); + EXPECT_TRUE(empty_string != byte_string); + EXPECT_TRUE(deleted_string != byte_string); + + ByteString byte_string_same1("hello"); + EXPECT_FALSE(byte_string != byte_string_same1); + EXPECT_FALSE(byte_string_same1 != byte_string); + + ByteString byte_string_same2(byte_string); + EXPECT_FALSE(byte_string != byte_string_same2); + EXPECT_FALSE(byte_string_same2 != byte_string); + + ByteString byte_string1("he"); + ByteString byte_string2("hellp"); + ByteString byte_string3("hellod"); + EXPECT_TRUE(byte_string != byte_string1); + EXPECT_TRUE(byte_string != byte_string2); + EXPECT_TRUE(byte_string != byte_string3); + EXPECT_TRUE(byte_string1 != byte_string); + EXPECT_TRUE(byte_string2 != byte_string); + EXPECT_TRUE(byte_string3 != byte_string); + + ByteStringView null_string_c; + ByteStringView empty_string_c(""); + EXPECT_FALSE(null_string != null_string_c); + EXPECT_FALSE(null_string != empty_string_c); + EXPECT_FALSE(empty_string != null_string_c); + EXPECT_FALSE(empty_string != empty_string_c); + EXPECT_FALSE(null_string_c != null_string); + EXPECT_FALSE(empty_string_c != null_string); + EXPECT_FALSE(null_string_c != empty_string); + EXPECT_FALSE(empty_string_c != empty_string); + + ByteStringView byte_string_c_same1("hello"); + EXPECT_FALSE(byte_string != byte_string_c_same1); + EXPECT_FALSE(byte_string_c_same1 != byte_string); + + ByteStringView byte_string_c1("he"); + ByteStringView byte_string_c2("hellp"); + ByteStringView byte_string_c3("hellod"); + EXPECT_TRUE(byte_string != byte_string_c1); + EXPECT_TRUE(byte_string != byte_string_c2); + EXPECT_TRUE(byte_string != byte_string_c3); + EXPECT_TRUE(byte_string_c1 != byte_string); + EXPECT_TRUE(byte_string_c2 != byte_string); + EXPECT_TRUE(byte_string_c3 != byte_string); + + const char* c_null_string = nullptr; + const char* c_empty_string = ""; + EXPECT_FALSE(null_string != c_null_string); + EXPECT_FALSE(null_string != c_empty_string); + EXPECT_FALSE(empty_string != c_null_string); + EXPECT_FALSE(empty_string != c_empty_string); + EXPECT_FALSE(deleted_string != c_null_string); + EXPECT_FALSE(deleted_string != c_empty_string); + EXPECT_FALSE(c_null_string != null_string); + EXPECT_FALSE(c_empty_string != null_string); + EXPECT_FALSE(c_null_string != empty_string); + EXPECT_FALSE(c_empty_string != empty_string); + EXPECT_FALSE(c_null_string != deleted_string); + EXPECT_FALSE(c_empty_string != deleted_string); + + const char* c_string_same1 = "hello"; + EXPECT_FALSE(byte_string != c_string_same1); + EXPECT_FALSE(c_string_same1 != byte_string); + + const char* c_string1 = "he"; + const char* c_string2 = "hellp"; + const char* c_string3 = "hellod"; + EXPECT_TRUE(byte_string != c_string1); + EXPECT_TRUE(byte_string != c_string2); + EXPECT_TRUE(byte_string != c_string3); + EXPECT_TRUE(c_string1 != byte_string); + EXPECT_TRUE(c_string2 != byte_string); + EXPECT_TRUE(c_string3 != byte_string); +} + +TEST(ByteStringView, Null) { + ByteStringView null_string; + EXPECT_FALSE(null_string.raw_str()); + EXPECT_EQ(0u, null_string.GetLength()); + EXPECT_TRUE(null_string.IsEmpty()); + + ByteStringView another_null_string; + EXPECT_EQ(null_string, another_null_string); + + ByteStringView copied_null_string(null_string); + EXPECT_FALSE(copied_null_string.raw_str()); + EXPECT_EQ(0u, copied_null_string.GetLength()); + EXPECT_TRUE(copied_null_string.IsEmpty()); + EXPECT_EQ(null_string, copied_null_string); + + ByteStringView empty_string(""); // Pointer to NUL, not NULL pointer. + EXPECT_TRUE(empty_string.raw_str()); + EXPECT_EQ(0u, empty_string.GetLength()); + EXPECT_TRUE(empty_string.IsEmpty()); + EXPECT_EQ(null_string, empty_string); + + ByteStringView assigned_null_string("initially not nullptr"); + assigned_null_string = null_string; + EXPECT_FALSE(assigned_null_string.raw_str()); + EXPECT_EQ(0u, assigned_null_string.GetLength()); + EXPECT_TRUE(assigned_null_string.IsEmpty()); + EXPECT_EQ(null_string, assigned_null_string); + + ByteStringView assigned_nullptr_string("initially not nullptr"); + assigned_nullptr_string = nullptr; + EXPECT_FALSE(assigned_nullptr_string.raw_str()); + EXPECT_EQ(0u, assigned_nullptr_string.GetLength()); + EXPECT_TRUE(assigned_nullptr_string.IsEmpty()); + EXPECT_EQ(null_string, assigned_nullptr_string); + + ByteStringView non_null_string("a"); + EXPECT_NE(null_string, non_null_string); +} + +TEST(ByteString, Concat) { + ByteString fred; + fred.Concat("FRED", 4); + EXPECT_EQ("FRED", fred); + + fred.Concat("DY", 2); + EXPECT_EQ("FREDDY", fred); + + fred.Delete(3, 3); + EXPECT_EQ("FRE", fred); + + fred.Concat("D", 1); + EXPECT_EQ("FRED", fred); + + ByteString copy = fred; + fred.Concat("DY", 2); + EXPECT_EQ("FREDDY", fred); + EXPECT_EQ("FRED", copy); +} + +TEST(ByteString, Remove) { + ByteString freed("FREED"); + freed.Remove('E'); + EXPECT_EQ("FRD", freed); + freed.Remove('F'); + EXPECT_EQ("RD", freed); + freed.Remove('D'); + EXPECT_EQ("R", freed); + freed.Remove('X'); + EXPECT_EQ("R", freed); + freed.Remove('R'); + EXPECT_EQ("", freed); + + ByteString empty; + empty.Remove('X'); + EXPECT_EQ("", empty); +} + +TEST(ByteString, RemoveCopies) { + ByteString freed("FREED"); + const char* old_buffer = freed.c_str(); + + // No change with single reference - no copy. + freed.Remove('Q'); + EXPECT_EQ("FREED", freed); + EXPECT_EQ(old_buffer, freed.c_str()); + + // Change with single reference - no copy. + freed.Remove('E'); + EXPECT_EQ("FRD", freed); + EXPECT_EQ(old_buffer, freed.c_str()); + + // No change with multiple references - no copy. + ByteString shared(freed); + freed.Remove('Q'); + EXPECT_EQ("FRD", freed); + EXPECT_EQ(old_buffer, freed.c_str()); + EXPECT_EQ(old_buffer, shared.c_str()); + + // Change with multiple references -- must copy. + freed.Remove('D'); + EXPECT_EQ("FR", freed); + EXPECT_NE(old_buffer, freed.c_str()); + EXPECT_EQ("FRD", shared); + EXPECT_EQ(old_buffer, shared.c_str()); +} + +TEST(ByteString, Replace) { + ByteString fred("FRED"); + fred.Replace("FR", "BL"); + EXPECT_EQ("BLED", fred); + fred.Replace("D", "DDY"); + EXPECT_EQ("BLEDDY", fred); + fred.Replace("LEDD", ""); + EXPECT_EQ("BY", fred); + fred.Replace("X", "CLAMS"); + EXPECT_EQ("BY", fred); + fred.Replace("BY", "HI"); + EXPECT_EQ("HI", fred); + fred.Replace("", "CLAMS"); + EXPECT_EQ("HI", fred); + fred.Replace("HI", ""); + EXPECT_EQ("", fred); +} + +TEST(ByteString, Insert) { + ByteString fred("FRED"); + EXPECT_EQ(5u, fred.Insert(0, 'S')); + EXPECT_EQ("SFRED", fred); + EXPECT_EQ(6u, fred.Insert(1, 'T')); + EXPECT_EQ("STFRED", fred); + EXPECT_EQ(7u, fred.Insert(4, 'U')); + EXPECT_EQ("STFRUED", fred); + EXPECT_EQ(8u, fred.Insert(7, 'V')); + EXPECT_EQ("STFRUEDV", fred); + EXPECT_EQ(8u, fred.Insert(12, 'P')); + EXPECT_EQ("STFRUEDV", fred); + { + ByteString empty; + EXPECT_EQ(1u, empty.Insert(0, 'X')); + EXPECT_EQ("X", empty); + } + { + ByteString empty; + EXPECT_EQ(0u, empty.Insert(5, 'X')); + EXPECT_NE("X", empty); + } +} + +TEST(ByteString, InsertAtFrontAndInsertAtBack) { + { + ByteString empty; + EXPECT_EQ(1u, empty.InsertAtFront('D')); + EXPECT_EQ("D", empty); + EXPECT_EQ(2u, empty.InsertAtFront('E')); + EXPECT_EQ("ED", empty); + EXPECT_EQ(3u, empty.InsertAtFront('R')); + EXPECT_EQ("RED", empty); + EXPECT_EQ(4u, empty.InsertAtFront('F')); + EXPECT_EQ("FRED", empty); + } + { + ByteString empty; + EXPECT_EQ(1u, empty.InsertAtBack('F')); + EXPECT_EQ("F", empty); + EXPECT_EQ(2u, empty.InsertAtBack('R')); + EXPECT_EQ("FR", empty); + EXPECT_EQ(3u, empty.InsertAtBack('E')); + EXPECT_EQ("FRE", empty); + EXPECT_EQ(4u, empty.InsertAtBack('D')); + EXPECT_EQ("FRED", empty); + } + { + ByteString empty; + EXPECT_EQ(1u, empty.InsertAtBack('E')); + EXPECT_EQ("E", empty); + EXPECT_EQ(2u, empty.InsertAtFront('R')); + EXPECT_EQ("RE", empty); + EXPECT_EQ(3u, empty.InsertAtBack('D')); + EXPECT_EQ("RED", empty); + EXPECT_EQ(4u, empty.InsertAtFront('F')); + EXPECT_EQ("FRED", empty); + } +} + +TEST(ByteString, Delete) { + ByteString fred("FRED"); + EXPECT_EQ(4u, fred.Delete(0, 0)); + EXPECT_EQ("FRED", fred); + EXPECT_EQ(2u, fred.Delete(0, 2)); + EXPECT_EQ("ED", fred); + EXPECT_EQ(1u, fred.Delete(1)); + EXPECT_EQ("E", fred); + EXPECT_EQ(0u, fred.Delete(0)); + EXPECT_EQ("", fred); + EXPECT_EQ(0u, fred.Delete(0)); + EXPECT_EQ("", fred); + + ByteString empty; + EXPECT_EQ(0u, empty.Delete(0)); + EXPECT_EQ("", empty); + EXPECT_EQ(0u, empty.Delete(1)); + EXPECT_EQ("", empty); +} + +TEST(ByteString, Mid) { + ByteString fred("FRED"); + EXPECT_EQ("", fred.Mid(0, 0)); + EXPECT_EQ("", fred.Mid(3, 0)); + EXPECT_EQ("FRED", fred.Mid(0, 4)); + EXPECT_EQ("RED", fred.Mid(1, 3)); + EXPECT_EQ("ED", fred.Mid(2, 2)); + EXPECT_EQ("D", fred.Mid(3, 1)); + EXPECT_EQ("F", fred.Mid(0, 1)); + EXPECT_EQ("R", fred.Mid(1, 1)); + EXPECT_EQ("E", fred.Mid(2, 1)); + EXPECT_EQ("D", fred.Mid(3, 1)); + EXPECT_EQ("FR", fred.Mid(0, 2)); + EXPECT_EQ("FRED", fred.Mid(0, 4)); + EXPECT_EQ("", fred.Mid(0, 10)); + + EXPECT_EQ("RED", fred.Mid(1, 3)); + EXPECT_EQ("", fred.Mid(4, 1)); + + ByteString empty; + EXPECT_EQ("", empty.Mid(0, 0)); +} + +TEST(ByteString, Left) { + ByteString fred("FRED"); + EXPECT_EQ("", fred.Left(0)); + EXPECT_EQ("F", fred.Left(1)); + EXPECT_EQ("FR", fred.Left(2)); + EXPECT_EQ("FRE", fred.Left(3)); + EXPECT_EQ("FRED", fred.Left(4)); + + EXPECT_EQ("", fred.Left(5)); + + ByteString empty; + EXPECT_EQ("", empty.Left(0)); + EXPECT_EQ("", empty.Left(1)); +} + +TEST(ByteString, Right) { + ByteString fred("FRED"); + EXPECT_EQ("", fred.Right(0)); + EXPECT_EQ("D", fred.Right(1)); + EXPECT_EQ("ED", fred.Right(2)); + EXPECT_EQ("RED", fred.Right(3)); + EXPECT_EQ("FRED", fred.Right(4)); + + EXPECT_EQ("", fred.Right(5)); + + ByteString empty; + EXPECT_EQ("", empty.Right(0)); + EXPECT_EQ("", empty.Right(1)); +} + +TEST(ByteString, Find) { + ByteString null_string; + EXPECT_FALSE(null_string.Find('a').has_value()); + EXPECT_FALSE(null_string.Find('\0').has_value()); + + ByteString empty_string(""); + EXPECT_FALSE(empty_string.Find('a').has_value()); + EXPECT_FALSE(empty_string.Find('\0').has_value()); + + pdfium::Optional result; + ByteString single_string("a"); + result = single_string.Find('a'); + ASSERT_TRUE(result.has_value()); + EXPECT_EQ(0u, result.value()); + EXPECT_FALSE(single_string.Find('b').has_value()); + EXPECT_FALSE(single_string.Find('\0').has_value()); + + ByteString longer_string("abccc"); + result = longer_string.Find('a'); + ASSERT_TRUE(result.has_value()); + EXPECT_EQ(0u, result.value()); + result = longer_string.Find('c'); + ASSERT_TRUE(result.has_value()); + EXPECT_EQ(2u, result.value()); + result = longer_string.Find('c', 3); + ASSERT_TRUE(result.has_value()); + EXPECT_EQ(3u, result.value()); + EXPECT_FALSE(longer_string.Find('d').has_value()); + EXPECT_FALSE(longer_string.Find('\0').has_value()); + + result = longer_string.Find("ab"); + ASSERT_TRUE(result.has_value()); + EXPECT_EQ(0u, result.value()); + result = longer_string.Find("ccc"); + ASSERT_TRUE(result.has_value()); + EXPECT_EQ(2u, result.value()); + result = longer_string.Find("cc", 3); + ASSERT_TRUE(result.has_value()); + EXPECT_EQ(3u, result.value()); + EXPECT_FALSE(longer_string.Find("d").has_value()); + + ByteString hibyte_string( + "ab\x8c" + "def"); + result = hibyte_string.Find('\x8c'); + ASSERT_TRUE(result.has_value()); + EXPECT_EQ(2u, result.value()); +} + +TEST(ByteString, ReverseFind) { + ByteString null_string; + EXPECT_FALSE(null_string.ReverseFind('a').has_value()); + EXPECT_FALSE(null_string.ReverseFind('\0').has_value()); + + ByteString empty_string(""); + EXPECT_FALSE(empty_string.ReverseFind('a').has_value()); + EXPECT_FALSE(empty_string.ReverseFind('\0').has_value()); + + pdfium::Optional result; + ByteString single_string("a"); + result = single_string.ReverseFind('a'); + ASSERT_TRUE(result.has_value()); + EXPECT_EQ(0u, result.value()); + EXPECT_FALSE(single_string.ReverseFind('b').has_value()); + EXPECT_FALSE(single_string.ReverseFind('\0').has_value()); + + ByteString longer_string("abccc"); + result = longer_string.ReverseFind('a'); + ASSERT_TRUE(result.has_value()); + EXPECT_EQ(0u, result.value()); + result = longer_string.ReverseFind('c'); + ASSERT_TRUE(result.has_value()); + EXPECT_EQ(4u, result.value()); + EXPECT_FALSE(longer_string.ReverseFind('\0').has_value()); + + ByteString hibyte_string( + "ab\x8c" + "def"); + result = hibyte_string.ReverseFind('\x8c'); + ASSERT_TRUE(result.has_value()); + EXPECT_EQ(2u, result.value()); +} + +TEST(ByteString, UpperLower) { + ByteString fred("F-Re.42D"); + fred.MakeLower(); + EXPECT_EQ("f-re.42d", fred); + fred.MakeUpper(); + EXPECT_EQ("F-RE.42D", fred); + + ByteString empty; + empty.MakeLower(); + EXPECT_EQ("", empty); + empty.MakeUpper(); + EXPECT_EQ("", empty); +} + +TEST(ByteString, TrimRight) { + ByteString fred(" FRED "); + fred.TrimRight(); + EXPECT_EQ(" FRED", fred); + fred.TrimRight('E'); + EXPECT_EQ(" FRED", fred); + fred.TrimRight('D'); + EXPECT_EQ(" FRE", fred); + fred.TrimRight("ERP"); + EXPECT_EQ(" F", fred); + + ByteString blank(" "); + blank.TrimRight("ERP"); + EXPECT_EQ(" ", blank); + blank.TrimRight('E'); + EXPECT_EQ(" ", blank); + blank.TrimRight(); + EXPECT_EQ("", blank); + + ByteString empty; + empty.TrimRight("ERP"); + EXPECT_EQ("", empty); + empty.TrimRight('E'); + EXPECT_EQ("", empty); + empty.TrimRight(); + EXPECT_EQ("", empty); +} + +TEST(ByteString, TrimRightCopies) { + { + // With a single reference, no copy takes place. + ByteString fred(" FRED "); + const char* old_buffer = fred.c_str(); + fred.TrimRight(); + EXPECT_EQ(" FRED", fred); + EXPECT_EQ(old_buffer, fred.c_str()); + } + { + // With multiple references, we must copy. + ByteString fred(" FRED "); + ByteString other_fred = fred; + const char* old_buffer = fred.c_str(); + fred.TrimRight(); + EXPECT_EQ(" FRED", fred); + EXPECT_EQ(" FRED ", other_fred); + EXPECT_NE(old_buffer, fred.c_str()); + } + { + // With multiple references, but no modifications, no copy. + ByteString fred("FRED"); + ByteString other_fred = fred; + const char* old_buffer = fred.c_str(); + fred.TrimRight(); + EXPECT_EQ("FRED", fred); + EXPECT_EQ("FRED", other_fred); + EXPECT_EQ(old_buffer, fred.c_str()); + } +} + +TEST(ByteString, TrimLeft) { + ByteString fred(" FRED "); + fred.TrimLeft(); + EXPECT_EQ("FRED ", fred); + fred.TrimLeft('E'); + EXPECT_EQ("FRED ", fred); + fred.TrimLeft('F'); + EXPECT_EQ("RED ", fred); + fred.TrimLeft("ERP"); + EXPECT_EQ("D ", fred); + + ByteString blank(" "); + blank.TrimLeft("ERP"); + EXPECT_EQ(" ", blank); + blank.TrimLeft('E'); + EXPECT_EQ(" ", blank); + blank.TrimLeft(); + EXPECT_EQ("", blank); + + ByteString empty; + empty.TrimLeft("ERP"); + EXPECT_EQ("", empty); + empty.TrimLeft('E'); + EXPECT_EQ("", empty); + empty.TrimLeft(); + EXPECT_EQ("", empty); +} + +TEST(ByteString, TrimLeftCopies) { + { + // With a single reference, no copy takes place. + ByteString fred(" FRED "); + const char* old_buffer = fred.c_str(); + fred.TrimLeft(); + EXPECT_EQ("FRED ", fred); + EXPECT_EQ(old_buffer, fred.c_str()); + } + { + // With multiple references, we must copy. + ByteString fred(" FRED "); + ByteString other_fred = fred; + const char* old_buffer = fred.c_str(); + fred.TrimLeft(); + EXPECT_EQ("FRED ", fred); + EXPECT_EQ(" FRED ", other_fred); + EXPECT_NE(old_buffer, fred.c_str()); + } + { + // With multiple references, but no modifications, no copy. + ByteString fred("FRED"); + ByteString other_fred = fred; + const char* old_buffer = fred.c_str(); + fred.TrimLeft(); + EXPECT_EQ("FRED", fred); + EXPECT_EQ("FRED", other_fred); + EXPECT_EQ(old_buffer, fred.c_str()); + } +} + +TEST(ByteString, Reserve) { + { + ByteString str; + str.Reserve(6); + const char* old_buffer = str.c_str(); + str += "ABCDEF"; + EXPECT_EQ(old_buffer, str.c_str()); + str += "Blah Blah Blah Blah Blah Blah"; + EXPECT_NE(old_buffer, str.c_str()); + } + { + ByteString str("A"); + str.Reserve(6); + const char* old_buffer = str.c_str(); + str += "BCDEF"; + EXPECT_EQ(old_buffer, str.c_str()); + str += "Blah Blah Blah Blah Blah Blah"; + EXPECT_NE(old_buffer, str.c_str()); + } +} + +TEST(ByteString, GetBuffer) { + { + ByteString str; + char* buffer = str.GetBuffer(12); + // NOLINTNEXTLINE(runtime/printf) + strcpy(buffer, "clams"); + str.ReleaseBuffer(str.GetStringLength()); + EXPECT_EQ("clams", str); + } + { + ByteString str("cl"); + char* buffer = str.GetBuffer(12); + // NOLINTNEXTLINE(runtime/printf) + strcpy(buffer + 2, "ams"); + str.ReleaseBuffer(str.GetStringLength()); + EXPECT_EQ("clams", str); + } +} + +TEST(ByteString, ReleaseBuffer) { + { + ByteString str; + str.Reserve(12); + str += "clams"; + const char* old_buffer = str.c_str(); + str.ReleaseBuffer(4); + EXPECT_EQ(old_buffer, str.c_str()); + EXPECT_EQ("clam", str); + } + { + ByteString str("c"); + str.Reserve(12); + str += "lams"; + const char* old_buffer = str.c_str(); + str.ReleaseBuffer(4); + EXPECT_EQ(old_buffer, str.c_str()); + EXPECT_EQ("clam", str); + } + { + ByteString str; + str.Reserve(200); + str += "clams"; + const char* old_buffer = str.c_str(); + str.ReleaseBuffer(4); + EXPECT_NE(old_buffer, str.c_str()); + EXPECT_EQ("clam", str); + } + { + ByteString str("c"); + str.Reserve(200); + str += "lams"; + const char* old_buffer = str.c_str(); + str.ReleaseBuffer(4); + EXPECT_NE(old_buffer, str.c_str()); + EXPECT_EQ("clam", str); + } +} + +TEST(ByteString, EmptyReverseIterator) { + ByteString empty; + auto iter = empty.rbegin(); + EXPECT_TRUE(iter == empty.rend()); + EXPECT_FALSE(iter != empty.rend()); + EXPECT_FALSE(iter < empty.rend()); +} + +TEST(ByteString, OneCharReverseIterator) { + ByteString one_str("a"); + auto iter = one_str.rbegin(); + EXPECT_FALSE(iter == one_str.rend()); + EXPECT_TRUE(iter != one_str.rend()); + EXPECT_TRUE(iter < one_str.rend()); + + char ch = *iter++; + EXPECT_EQ('a', ch); + EXPECT_TRUE(iter == one_str.rend()); + EXPECT_FALSE(iter != one_str.rend()); + EXPECT_FALSE(iter < one_str.rend()); +} + +TEST(ByteString, MultiCharReverseIterator) { + ByteString multi_str("abcd"); + auto iter = multi_str.rbegin(); + EXPECT_FALSE(iter == multi_str.rend()); + + char ch = *iter++; + EXPECT_EQ('d', ch); + EXPECT_EQ('c', *iter); + EXPECT_FALSE(iter == multi_str.rend()); + + ch = *(++iter); + EXPECT_EQ('b', ch); + EXPECT_EQ('b', *iter); + EXPECT_FALSE(iter == multi_str.rend()); + + ch = *iter++; + EXPECT_EQ('b', ch); + EXPECT_EQ('a', *iter); + EXPECT_FALSE(iter == multi_str.rend()); + + ch = *iter++; + EXPECT_EQ('a', ch); + EXPECT_TRUE(iter == multi_str.rend()); + + ch = *(--iter); + EXPECT_EQ('a', ch); + EXPECT_EQ('a', *iter); + EXPECT_FALSE(iter == multi_str.rend()); + + ch = *iter--; + EXPECT_EQ('a', ch); + EXPECT_EQ('b', *iter); + EXPECT_FALSE(iter == multi_str.rend()); + + ch = *iter--; + EXPECT_EQ('b', ch); + EXPECT_EQ('c', *iter); + EXPECT_FALSE(iter == multi_str.rend()); + + ch = *(--iter); + EXPECT_EQ('d', ch); + EXPECT_EQ('d', *iter); + EXPECT_TRUE(iter == multi_str.rbegin()); +} + +TEST(ByteStringView, NotNull) { + ByteStringView string3("abc"); + ByteStringView string6("abcdef"); + ByteStringView alternate_string3("abcdef", 3); + ByteStringView embedded_nul_string7("abc\0def", 7); + ByteStringView illegal_string7("abcdef", 7); + + EXPECT_EQ(3u, string3.GetLength()); + EXPECT_EQ(6u, string6.GetLength()); + EXPECT_EQ(3u, alternate_string3.GetLength()); + EXPECT_EQ(7u, embedded_nul_string7.GetLength()); + EXPECT_EQ(7u, illegal_string7.GetLength()); + + EXPECT_NE(string3, string6); + EXPECT_EQ(string3, alternate_string3); + EXPECT_NE(string3, embedded_nul_string7); + EXPECT_NE(string3, illegal_string7); + EXPECT_NE(string6, alternate_string3); + EXPECT_NE(string6, embedded_nul_string7); + EXPECT_NE(string6, illegal_string7); + EXPECT_NE(alternate_string3, embedded_nul_string7); + EXPECT_NE(alternate_string3, illegal_string7); + EXPECT_NE(embedded_nul_string7, illegal_string7); + + ByteStringView copied_string3(string3); + ByteStringView copied_alternate_string3(alternate_string3); + ByteStringView copied_embedded_nul_string7(embedded_nul_string7); + + EXPECT_EQ(string3, copied_string3); + EXPECT_EQ(alternate_string3, copied_alternate_string3); + EXPECT_EQ(embedded_nul_string7, copied_embedded_nul_string7); + + ByteStringView assigned_string3("intially something else"); + ByteStringView assigned_alternate_string3("initally something else"); + ByteStringView assigned_ptr_string3("initially something else"); + ByteStringView assigned_embedded_nul_string7("initially something else"); + + assigned_string3 = string3; + assigned_alternate_string3 = alternate_string3; + assigned_ptr_string3 = "abc"; + assigned_embedded_nul_string7 = embedded_nul_string7; + EXPECT_EQ(string3, assigned_string3); + EXPECT_EQ(alternate_string3, assigned_alternate_string3); + EXPECT_EQ(alternate_string3, assigned_ptr_string3); + EXPECT_EQ(embedded_nul_string7, assigned_embedded_nul_string7); +} + +TEST(ByteStringView, FromChar) { + ByteStringView null_string; + ByteStringView lower_a_string("a"); + + // Must have lvalues that outlive the corresponding ByteStringC. + char nul = '\0'; + char lower_a = 'a'; + ByteStringView nul_string_from_char(nul); + ByteStringView lower_a_string_from_char(lower_a); + + // Pointer to nul, not nullptr ptr, hence length 1 ... + EXPECT_EQ(1u, nul_string_from_char.GetLength()); + EXPECT_NE(null_string, nul_string_from_char); + + EXPECT_EQ(1u, lower_a_string_from_char.GetLength()); + EXPECT_EQ(lower_a_string, lower_a_string_from_char); + EXPECT_NE(nul_string_from_char, lower_a_string_from_char); + + ByteStringView longer_string("ab"); + EXPECT_NE(longer_string, lower_a_string_from_char); +} + +TEST(ByteStringView, FromVector) { + std::vector null_vec; + ByteStringView null_string(null_vec); + EXPECT_EQ(0u, null_string.GetLength()); + + std::vector lower_a_vec(10, static_cast('a')); + ByteStringView lower_a_string(lower_a_vec); + EXPECT_EQ(static_cast(10), lower_a_string.GetLength()); + EXPECT_EQ("aaaaaaaaaa", lower_a_string); + + std::vector cleared_vec; + cleared_vec.push_back(42); + cleared_vec.pop_back(); + ByteStringView cleared_string(cleared_vec); + EXPECT_EQ(0u, cleared_string.GetLength()); + EXPECT_EQ(nullptr, cleared_string.raw_str()); +} + +TEST(ByteStringView, GetID) { + ByteStringView null_string; + EXPECT_EQ(0u, null_string.GetID()); + + ByteStringView empty_string(""); + EXPECT_EQ(0u, empty_string.GetID()); + + ByteStringView short_string("ab"); + EXPECT_EQ(FXBSTR_ID('a', 'b', 0, 0), short_string.GetID()); + + ByteStringView longer_string("abcdef"); + EXPECT_EQ(FXBSTR_ID('a', 'b', 'c', 'd'), longer_string.GetID()); +} + +TEST(ByteStringView, Find) { + ByteStringView null_string; + EXPECT_FALSE(null_string.Find('a').has_value()); + EXPECT_FALSE(null_string.Find('\0').has_value()); + + ByteStringView empty_string(""); + EXPECT_FALSE(empty_string.Find('a').has_value()); + EXPECT_FALSE(empty_string.Find('\0').has_value()); + + pdfium::Optional result; + ByteStringView single_string("a"); + result = single_string.Find('a'); + ASSERT_TRUE(result.has_value()); + EXPECT_EQ(0u, result.value()); + EXPECT_FALSE(single_string.Find('b').has_value()); + EXPECT_FALSE(single_string.Find('\0').has_value()); + + ByteStringView longer_string("abccc"); + result = longer_string.Find('a'); + ASSERT_TRUE(result.has_value()); + EXPECT_EQ(0u, result.value()); + result = longer_string.Find('c'); + ASSERT_TRUE(result.has_value()); + EXPECT_EQ(2u, result.value()); + EXPECT_FALSE(longer_string.Find('d').has_value()); + EXPECT_FALSE(longer_string.Find('\0').has_value()); + + ByteStringView hibyte_string( + "ab\x8c" + "def"); + result = hibyte_string.Find('\x8c'); + ASSERT_TRUE(result.has_value()); + EXPECT_EQ(2u, result.value()); +} + +TEST(ByteStringView, Mid) { + ByteStringView null_string; + EXPECT_EQ(null_string, null_string.Mid(0, 1)); + EXPECT_EQ(null_string, null_string.Mid(1, 1)); + + ByteStringView empty_string(""); + EXPECT_EQ("", empty_string.Mid(0, 1)); + EXPECT_EQ("", empty_string.Mid(1, 1)); + + ByteStringView single_character("a"); + EXPECT_EQ("", single_character.Mid(0, 0)); + EXPECT_EQ(single_character, single_character.Mid(0, 1)); + EXPECT_EQ("", single_character.Mid(1, 0)); + EXPECT_EQ("", single_character.Mid(1, 1)); + + ByteStringView longer_string("abcdef"); + EXPECT_EQ(longer_string, longer_string.Mid(0, 6)); + EXPECT_EQ("", longer_string.Mid(0, 187)); + + ByteStringView leading_substring("ab"); + EXPECT_EQ(leading_substring, longer_string.Mid(0, 2)); + + ByteStringView middle_substring("bcde"); + EXPECT_EQ(middle_substring, longer_string.Mid(1, 4)); + + ByteStringView trailing_substring("ef"); + EXPECT_EQ(trailing_substring, longer_string.Mid(4, 2)); + EXPECT_EQ("", longer_string.Mid(4, 3)); +} + +TEST(ByteStringView, TrimmedRight) { + ByteStringView fred("FRED"); + EXPECT_EQ("FRED", fred.TrimmedRight('E')); + EXPECT_EQ("FRE", fred.TrimmedRight('D')); + ByteStringView fredd("FREDD"); + EXPECT_EQ("FRE", fred.TrimmedRight('D')); +} + +TEST(ByteStringView, ElementAccess) { + // ByteStringView includes the NUL terminator for non-empty strings. + ByteStringView abc("abc"); + EXPECT_EQ('a', static_cast(abc[0])); + EXPECT_EQ('b', static_cast(abc[1])); + EXPECT_EQ('c', static_cast(abc[2])); +#ifndef NDEBUG + EXPECT_DEATH({ abc[3]; }, ".*"); +#endif +} + +TEST(ByteStringView, OperatorLT) { + ByteStringView empty; + ByteStringView a("a"); + ByteStringView abc("abc"); + ByteStringView def("def"); + + EXPECT_FALSE(empty < empty); + EXPECT_FALSE(a < a); + EXPECT_FALSE(abc < abc); + EXPECT_FALSE(def < def); + + EXPECT_TRUE(empty < a); + EXPECT_FALSE(a < empty); + + EXPECT_TRUE(empty < abc); + EXPECT_FALSE(abc < empty); + + EXPECT_TRUE(empty < def); + EXPECT_FALSE(def < empty); + + EXPECT_TRUE(a < abc); + EXPECT_FALSE(abc < a); + + EXPECT_TRUE(a < def); + EXPECT_FALSE(def < a); + + EXPECT_TRUE(abc < def); + EXPECT_FALSE(def < abc); +} + +TEST(ByteStringView, OperatorEQ) { + ByteStringView byte_string_c("hello"); + EXPECT_TRUE(byte_string_c == byte_string_c); + + ByteStringView byte_string_c_same1("hello"); + EXPECT_TRUE(byte_string_c == byte_string_c_same1); + EXPECT_TRUE(byte_string_c_same1 == byte_string_c); + + ByteStringView byte_string_c_same2(byte_string_c); + EXPECT_TRUE(byte_string_c == byte_string_c_same2); + EXPECT_TRUE(byte_string_c_same2 == byte_string_c); + + ByteStringView byte_string_c1("he"); + ByteStringView byte_string_c2("hellp"); + ByteStringView byte_string_c3("hellod"); + EXPECT_FALSE(byte_string_c == byte_string_c1); + EXPECT_FALSE(byte_string_c == byte_string_c2); + EXPECT_FALSE(byte_string_c == byte_string_c3); + EXPECT_FALSE(byte_string_c1 == byte_string_c); + EXPECT_FALSE(byte_string_c2 == byte_string_c); + EXPECT_FALSE(byte_string_c3 == byte_string_c); + + ByteString byte_string_same1("hello"); + EXPECT_TRUE(byte_string_c == byte_string_same1); + EXPECT_TRUE(byte_string_same1 == byte_string_c); + + ByteString byte_string1("he"); + ByteString byte_string2("hellp"); + ByteString byte_string3("hellod"); + EXPECT_FALSE(byte_string_c == byte_string1); + EXPECT_FALSE(byte_string_c == byte_string2); + EXPECT_FALSE(byte_string_c == byte_string3); + EXPECT_FALSE(byte_string1 == byte_string_c); + EXPECT_FALSE(byte_string2 == byte_string_c); + EXPECT_FALSE(byte_string3 == byte_string_c); + + const char* c_string_same1 = "hello"; + EXPECT_TRUE(byte_string_c == c_string_same1); + EXPECT_TRUE(c_string_same1 == byte_string_c); + + const char* c_string1 = "he"; + const char* c_string2 = "hellp"; + const char* c_string3 = "hellod"; + EXPECT_FALSE(byte_string_c == c_string1); + EXPECT_FALSE(byte_string_c == c_string2); + EXPECT_FALSE(byte_string_c == c_string3); + + EXPECT_FALSE(c_string1 == byte_string_c); + EXPECT_FALSE(c_string2 == byte_string_c); + EXPECT_FALSE(c_string3 == byte_string_c); +} + +TEST(ByteStringView, OperatorNE) { + ByteStringView byte_string_c("hello"); + EXPECT_FALSE(byte_string_c != byte_string_c); + + ByteStringView byte_string_c_same1("hello"); + EXPECT_FALSE(byte_string_c != byte_string_c_same1); + EXPECT_FALSE(byte_string_c_same1 != byte_string_c); + + ByteStringView byte_string_c_same2(byte_string_c); + EXPECT_FALSE(byte_string_c != byte_string_c_same2); + EXPECT_FALSE(byte_string_c_same2 != byte_string_c); + + ByteStringView byte_string_c1("he"); + ByteStringView byte_string_c2("hellp"); + ByteStringView byte_string_c3("hellod"); + EXPECT_TRUE(byte_string_c != byte_string_c1); + EXPECT_TRUE(byte_string_c != byte_string_c2); + EXPECT_TRUE(byte_string_c != byte_string_c3); + EXPECT_TRUE(byte_string_c1 != byte_string_c); + EXPECT_TRUE(byte_string_c2 != byte_string_c); + EXPECT_TRUE(byte_string_c3 != byte_string_c); + + ByteString byte_string_same1("hello"); + EXPECT_FALSE(byte_string_c != byte_string_same1); + EXPECT_FALSE(byte_string_same1 != byte_string_c); + + ByteString byte_string1("he"); + ByteString byte_string2("hellp"); + ByteString byte_string3("hellod"); + EXPECT_TRUE(byte_string_c != byte_string1); + EXPECT_TRUE(byte_string_c != byte_string2); + EXPECT_TRUE(byte_string_c != byte_string3); + EXPECT_TRUE(byte_string1 != byte_string_c); + EXPECT_TRUE(byte_string2 != byte_string_c); + EXPECT_TRUE(byte_string3 != byte_string_c); + + const char* c_string_same1 = "hello"; + EXPECT_FALSE(byte_string_c != c_string_same1); + EXPECT_FALSE(c_string_same1 != byte_string_c); + + const char* c_string1 = "he"; + const char* c_string2 = "hellp"; + const char* c_string3 = "hellod"; + EXPECT_TRUE(byte_string_c != c_string1); + EXPECT_TRUE(byte_string_c != c_string2); + EXPECT_TRUE(byte_string_c != c_string3); + + EXPECT_TRUE(c_string1 != byte_string_c); + EXPECT_TRUE(c_string2 != byte_string_c); + EXPECT_TRUE(c_string3 != byte_string_c); +} + +TEST(ByteStringView, NullIterator) { + ByteStringView null_str; + int32_t sum = 0; + bool any_present = false; + for (const auto& c : null_str) { + sum += c; // Avoid unused arg warnings. + any_present = true; + } + EXPECT_FALSE(any_present); + EXPECT_EQ(0, sum); +} + +TEST(ByteStringView, EmptyIterator) { + ByteStringView empty_str(""); + int32_t sum = 0; + bool any_present = false; + for (const auto& c : empty_str) { + any_present = true; + sum += c; // Avoid unused arg warnings. + } + EXPECT_FALSE(any_present); + EXPECT_EQ(0, sum); +} + +TEST(ByteStringView, OneCharIterator) { + ByteStringView one_str("a"); + int32_t sum = 0; + bool any_present = false; + for (const auto& c : one_str) { + any_present = true; + sum += c; // Avoid unused arg warnings. + } + EXPECT_TRUE(any_present); + EXPECT_EQ('a', sum); +} + +TEST(ByteStringView, MultiCharIterator) { + ByteStringView one_str("abc"); + int32_t sum = 0; + bool any_present = false; + for (const auto& c : one_str) { + any_present = true; + sum += c; // Avoid unused arg warnings. + } + EXPECT_TRUE(any_present); + EXPECT_EQ('a' + 'b' + 'c', sum); +} + +TEST(ByteStringView, EmptyReverseIterator) { + ByteStringView empty; + auto iter = empty.rbegin(); + EXPECT_TRUE(iter == empty.rend()); + EXPECT_FALSE(iter != empty.rend()); + EXPECT_FALSE(iter < empty.rend()); +} + +TEST(ByteStringView, OneCharReverseIterator) { + ByteStringView one_str("a"); + auto iter = one_str.rbegin(); + EXPECT_FALSE(iter == one_str.rend()); + EXPECT_TRUE(iter != one_str.rend()); + EXPECT_TRUE(iter < one_str.rend()); + + char ch = *iter++; + EXPECT_EQ('a', ch); + EXPECT_TRUE(iter == one_str.rend()); + EXPECT_FALSE(iter != one_str.rend()); + EXPECT_FALSE(iter < one_str.rend()); +} + +TEST(ByteStringView, MultiCharReverseIterator) { + ByteStringView multi_str("abcd"); + auto iter = multi_str.rbegin(); + EXPECT_FALSE(iter == multi_str.rend()); + + char ch = *iter++; + EXPECT_EQ('d', ch); + EXPECT_EQ('c', *iter); + EXPECT_FALSE(iter == multi_str.rend()); + + ch = *(++iter); + EXPECT_EQ('b', ch); + EXPECT_EQ('b', *iter); + EXPECT_FALSE(iter == multi_str.rend()); + + ch = *iter++; + EXPECT_EQ('b', ch); + EXPECT_EQ('a', *iter); + EXPECT_FALSE(iter == multi_str.rend()); + + ch = *iter++; + EXPECT_EQ('a', ch); + EXPECT_TRUE(iter == multi_str.rend()); + + ch = *(--iter); + EXPECT_EQ('a', ch); + EXPECT_EQ('a', *iter); + EXPECT_FALSE(iter == multi_str.rend()); + + ch = *iter--; + EXPECT_EQ('a', ch); + EXPECT_EQ('b', *iter); + EXPECT_FALSE(iter == multi_str.rend()); + + ch = *iter--; + EXPECT_EQ('b', ch); + EXPECT_EQ('c', *iter); + EXPECT_FALSE(iter == multi_str.rend()); + + ch = *(--iter); + EXPECT_EQ('d', ch); + EXPECT_EQ('d', *iter); + EXPECT_TRUE(iter == multi_str.rbegin()); +} + +TEST(ByteStringView, AnyAllNoneOf) { + ByteStringView str("aaaaaaaaaaaaaaaaab"); + EXPECT_FALSE(std::all_of(str.begin(), str.end(), + [](const char& c) { return c == 'a'; })); + + EXPECT_FALSE(std::none_of(str.begin(), str.end(), + [](const char& c) { return c == 'a'; })); + + EXPECT_TRUE(std::any_of(str.begin(), str.end(), + [](const char& c) { return c == 'a'; })); + + EXPECT_TRUE(pdfium::ContainsValue(str, 'a')); + EXPECT_TRUE(pdfium::ContainsValue(str, 'b')); + EXPECT_FALSE(pdfium::ContainsValue(str, 'z')); +} + +TEST(ByteString, FormatWidth) { + { + ByteString str; + str.Format("%5d", 1); + EXPECT_EQ(" 1", str); + } + + { + ByteString str; + str.Format("%d", 1); + EXPECT_EQ("1", str); + } + + { + ByteString str; + str.Format("%*d", 5, 1); + EXPECT_EQ(" 1", str); + } + + { + ByteString str; + str.Format("%-1d", 1); + EXPECT_EQ("1", str); + } + + { + ByteString str; + str.Format("%0d", 1); + EXPECT_EQ("1", str); + } +} + +TEST(ByteString, FormatPrecision) { + { + ByteString str; + str.Format("%.2f", 1.12345); + EXPECT_EQ("1.12", str); + } + + { + ByteString str; + str.Format("%.*f", 3, 1.12345); + EXPECT_EQ("1.123", str); + } + + { + ByteString str; + str.Format("%f", 1.12345); + EXPECT_EQ("1.123450", str); + } + + { + ByteString str; + str.Format("%-1f", 1.12345); + EXPECT_EQ("1.123450", str); + } + + { + ByteString str; + str.Format("%0f", 1.12345); + EXPECT_EQ("1.123450", str); + } +} + +TEST(ByteString, Empty) { + ByteString empty_str; + EXPECT_TRUE(empty_str.IsEmpty()); + EXPECT_EQ(0u, empty_str.GetLength()); + const char* cstr = empty_str.c_str(); + EXPECT_EQ(0u, FXSYS_strlen(cstr)); +} + +TEST(ByteString, InitializerList) { + ByteString many_str({"clams", " and ", "oysters"}); + EXPECT_EQ("clams and oysters", many_str); + many_str = {"fish", " and ", "chips", " and ", "soda"}; + EXPECT_EQ("fish and chips and soda", many_str); +} + +TEST(ByteString, NullIterator) { + ByteString null_str; + int32_t sum = 0; + bool any_present = false; + for (const auto& c : null_str) { + sum += c; // Avoid unused arg warnings. + any_present = true; + } + EXPECT_FALSE(any_present); + EXPECT_EQ(0, sum); +} + +TEST(ByteString, EmptyIterator) { + ByteString empty_str(""); + int32_t sum = 0; + bool any_present = false; + for (const auto& c : empty_str) { + any_present = true; + sum += c; // Avoid unused arg warnings. + } + EXPECT_FALSE(any_present); + EXPECT_EQ(0, sum); +} + +TEST(ByteString, OneCharIterator) { + ByteString one_str("a"); + int32_t sum = 0; + bool any_present = false; + for (const auto& c : one_str) { + any_present = true; + sum += c; // Avoid unused arg warnings. + } + EXPECT_TRUE(any_present); + EXPECT_EQ('a', sum); +} + +TEST(ByteString, MultiCharIterator) { + ByteString one_str("abc"); + int32_t sum = 0; + bool any_present = false; + for (const auto& c : one_str) { + any_present = true; + sum += c; // Avoid unused arg warnings. + } + EXPECT_TRUE(any_present); + EXPECT_EQ('a' + 'b' + 'c', sum); +} + +TEST(ByteString, AnyAllNoneOf) { + ByteString str("aaaaaaaaaaaaaaaaab"); + EXPECT_FALSE(std::all_of(str.begin(), str.end(), + [](const char& c) { return c == 'a'; })); + + EXPECT_FALSE(std::none_of(str.begin(), str.end(), + [](const char& c) { return c == 'a'; })); + + EXPECT_TRUE(std::any_of(str.begin(), str.end(), + [](const char& c) { return c == 'a'; })); + + EXPECT_TRUE(pdfium::ContainsValue(str, 'a')); + EXPECT_TRUE(pdfium::ContainsValue(str, 'b')); + EXPECT_FALSE(pdfium::ContainsValue(str, 'z')); +} + +TEST(CFX_BytrString, EqualNoCase) { + ByteString str("aaa"); + EXPECT_TRUE(str.EqualNoCase("aaa")); + EXPECT_TRUE(str.EqualNoCase("AAA")); + EXPECT_TRUE(str.EqualNoCase("aaA")); + EXPECT_TRUE(str.EqualNoCase("Aaa")); + EXPECT_FALSE(str.EqualNoCase("aab")); + EXPECT_FALSE(str.EqualNoCase("aaaa")); + EXPECT_FALSE(str.EqualNoCase("BBBB")); + EXPECT_FALSE(str.EqualNoCase("a")); + EXPECT_FALSE(str.EqualNoCase("")); +} + +TEST(ByteString, OStreamOverload) { + std::ostringstream stream; + + // Basic case, empty string + ByteString str; + stream << str; + EXPECT_EQ("", stream.str()); + + // Basic case, non-empty string + str = "def"; + stream.str(""); + stream << "abc" << str << "ghi"; + EXPECT_EQ("abcdefghi", stream.str()); + + // Changing the ByteString does not change the stream it was written to. + str = "123"; + EXPECT_EQ("abcdefghi", stream.str()); + + // Writing it again to the stream will use the latest value. + stream.str(""); + stream << "abc" << str << "ghi"; + EXPECT_EQ("abc123ghi", stream.str()); + + char stringWithNulls[]{'x', 'y', '\0', 'z'}; + + // Writing a ByteString with nulls and no specified length treats it as + // a C-style null-terminated string. + str = ByteString(stringWithNulls); + EXPECT_EQ(2u, str.GetLength()); + stream.str(""); + stream << str; + EXPECT_EQ(2u, stream.tellp()); + + // Writing a ByteString with nulls but specifying its length treats it as + // a C++-style string. + str = ByteString(stringWithNulls, 4); + EXPECT_EQ(4u, str.GetLength()); + stream.str(""); + stream << str; + EXPECT_EQ(4u, stream.tellp()); + + // << operators can be chained. + ByteString str1("abc"); + ByteString str2("def"); + stream.str(""); + stream << str1 << str2; + EXPECT_EQ("abcdef", stream.str()); +} + +TEST(ByteStringView, OStreamOverload) { + // Basic case, empty string + { + std::ostringstream stream; + ByteStringView str; + stream << str; + EXPECT_EQ("", stream.str()); + } + + // Basic case, non-empty string + { + std::ostringstream stream; + ByteStringView str("def"); + stream << "abc" << str << "ghi"; + EXPECT_EQ("abcdefghi", stream.str()); + } + + // Changing the ByteStringView does not change the stream it was written to. + { + std::ostringstream stream; + ByteStringView str("abc"); + stream << str; + str = "123"; + EXPECT_EQ("abc", stream.str()); + } + + // Writing it again to the stream will use the latest value. + { + std::ostringstream stream; + ByteStringView str("abc"); + stream << str; + stream.str(""); + str = "123"; + stream << str; + EXPECT_EQ("123", stream.str()); + } + + // Writing a ByteStringView with nulls and no specified length treats it as + // a C-style null-terminated string. + { + std::ostringstream stream; + char stringWithNulls[]{'x', 'y', '\0', 'z'}; + ByteStringView str(stringWithNulls); + EXPECT_EQ(2u, str.GetLength()); + stream << str; + EXPECT_EQ(2u, stream.tellp()); + str = ""; + } + + // Writing a ByteStringView with nulls but specifying its length treats it as + // a C++-style string. + { + std::ostringstream stream; + char stringWithNulls[]{'x', 'y', '\0', 'z'}; + ByteStringView str(stringWithNulls, 4); + EXPECT_EQ(4u, str.GetLength()); + stream << str; + EXPECT_EQ(4u, stream.tellp()); + str = ""; + } + + // << operators can be chained. + { + std::ostringstream stream; + ByteStringView str1("abc"); + ByteStringView str2("def"); + stream << str1 << str2; + EXPECT_EQ("abcdef", stream.str()); + } +} + +TEST(ByteString, FormatInteger) { + // Base case of 0. + EXPECT_EQ("0", ByteString::FormatInteger(0)); + + // Positive ordinary number. + EXPECT_EQ("123456", ByteString::FormatInteger(123456)); + + // Negative ordinary number. + EXPECT_EQ("-123456", ByteString::FormatInteger(-123456)); + + // int limits. + EXPECT_EQ("2147483647", ByteString::FormatInteger(INT_MAX)); + EXPECT_EQ("-2147483648", ByteString::FormatInteger(INT_MIN)); +} diff --git a/core/fxcrt/cfx_binarybuf.h b/core/fxcrt/cfx_binarybuf.h index 4c795eda0b..186d8d1b88 100644 --- a/core/fxcrt/cfx_binarybuf.h +++ b/core/fxcrt/cfx_binarybuf.h @@ -27,7 +27,7 @@ class CFX_BinaryBuf { void Clear(); void EstimateSize(FX_STRSIZE size, FX_STRSIZE alloc_step = 0); void AppendBlock(const void* pBuf, FX_STRSIZE size); - void AppendString(const CFX_ByteString& str) { + void AppendString(const ByteString& str) { AppendBlock(str.c_str(), str.GetLength()); } diff --git a/core/fxcrt/cfx_blockbuffer.cpp b/core/fxcrt/cfx_blockbuffer.cpp index aeef5653e8..13134f0e7b 100644 --- a/core/fxcrt/cfx_blockbuffer.cpp +++ b/core/fxcrt/cfx_blockbuffer.cpp @@ -70,19 +70,19 @@ void CFX_BlockBuffer::DeleteTextChars(size_t count) { m_DataLength -= count; } -CFX_WideString CFX_BlockBuffer::GetTextData(size_t start, size_t length) const { +WideString CFX_BlockBuffer::GetTextData(size_t start, size_t length) const { if (m_BufferSize <= m_StartPosition + 1 || length == 0) - return CFX_WideString(); + return WideString(); size_t maybeDataLength = m_BufferSize - 1 - m_StartPosition; if (start > maybeDataLength) - return CFX_WideString(); + return WideString(); length = std::min(length, maybeDataLength); - CFX_WideString wsTextData; + WideString wsTextData; wchar_t* pBuf = wsTextData.GetBuffer(length); if (!pBuf) - return CFX_WideString(); + return WideString(); size_t startBlock = 0; size_t startInner = 0; diff --git a/core/fxcrt/cfx_blockbuffer.h b/core/fxcrt/cfx_blockbuffer.h index 867449074d..423aa6820b 100644 --- a/core/fxcrt/cfx_blockbuffer.h +++ b/core/fxcrt/cfx_blockbuffer.h @@ -37,7 +37,7 @@ class CFX_BlockBuffer { void SetTextChar(size_t iIndex, wchar_t ch); void DeleteTextChars(size_t iCount); - CFX_WideString GetTextData(size_t iStart, size_t iLength) const; + WideString GetTextData(size_t iStart, size_t iLength) const; private: std::pair TextDataIndex2BufIndex(const size_t iIndex) const; diff --git a/core/fxcrt/cfx_bytestring.cpp b/core/fxcrt/cfx_bytestring.cpp deleted file mode 100644 index 073591a5ab..0000000000 --- a/core/fxcrt/cfx_bytestring.cpp +++ /dev/null @@ -1,780 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "core/fxcrt/cfx_bytestring.h" - -#include - -#include -#include -#include - -#include "core/fxcrt/cfx_string_pool_template.h" -#include "core/fxcrt/cfx_utf8decoder.h" -#include "core/fxcrt/fx_codepage.h" -#include "core/fxcrt/fx_extension.h" -#include "core/fxcrt/fx_safe_types.h" -#include "third_party/base/numerics/safe_math.h" -#include "third_party/base/stl_util.h" - -template class CFX_StringDataTemplate; -template class CFX_StringCTemplate; -template class CFX_StringPoolTemplate; -template struct std::hash; - -namespace { - -const char* FX_strstr(const char* haystack, - int haystack_len, - const char* needle, - int needle_len) { - if (needle_len > haystack_len || needle_len == 0) { - return nullptr; - } - const char* end_ptr = haystack + haystack_len - needle_len; - while (haystack <= end_ptr) { - int i = 0; - while (1) { - if (haystack[i] != needle[i]) { - break; - } - i++; - if (i == needle_len) { - return haystack; - } - } - haystack++; - } - return nullptr; -} - -#ifndef NDEBUG -bool IsValidCodePage(uint16_t codepage) { - switch (codepage) { - case FX_CODEPAGE_DefANSI: - case FX_CODEPAGE_ShiftJIS: - case FX_CODEPAGE_ChineseSimplified: - case FX_CODEPAGE_Hangul: - case FX_CODEPAGE_ChineseTraditional: - return true; - default: - return false; - } -} -#endif - -CFX_ByteString GetByteString(uint16_t codepage, const CFX_WideStringC& wstr) { - ASSERT(IsValidCodePage(codepage)); - - int src_len = wstr.GetLength(); - int dest_len = - FXSYS_WideCharToMultiByte(codepage, 0, wstr.unterminated_c_str(), src_len, - nullptr, 0, nullptr, nullptr); - if (!dest_len) - return CFX_ByteString(); - - CFX_ByteString bstr; - char* dest_buf = bstr.GetBuffer(dest_len); - FXSYS_WideCharToMultiByte(codepage, 0, wstr.unterminated_c_str(), src_len, - dest_buf, dest_len, nullptr, nullptr); - bstr.ReleaseBuffer(dest_len); - return bstr; -} - -} // namespace - -static_assert(sizeof(CFX_ByteString) <= sizeof(char*), - "Strings must not require more space than pointers"); - -CFX_ByteString::CFX_ByteString(const char* pStr, FX_STRSIZE nLen) { - if (nLen) - m_pData.Reset(StringData::Create(pStr, nLen)); -} - -CFX_ByteString::CFX_ByteString(const uint8_t* pStr, FX_STRSIZE nLen) { - if (nLen) - m_pData.Reset( - StringData::Create(reinterpret_cast(pStr), nLen)); -} - -CFX_ByteString::CFX_ByteString() {} - -CFX_ByteString::CFX_ByteString(const CFX_ByteString& other) - : m_pData(other.m_pData) {} - -CFX_ByteString::CFX_ByteString(CFX_ByteString&& other) noexcept { - m_pData.Swap(other.m_pData); -} - -CFX_ByteString::CFX_ByteString(char ch) { - m_pData.Reset(StringData::Create(1)); - m_pData->m_String[0] = ch; -} - -CFX_ByteString::CFX_ByteString(const char* ptr) - : CFX_ByteString(ptr, ptr ? FXSYS_strlen(ptr) : 0) {} - -CFX_ByteString::CFX_ByteString(const CFX_ByteStringC& stringSrc) { - if (!stringSrc.IsEmpty()) - m_pData.Reset(StringData::Create(stringSrc.unterminated_c_str(), - stringSrc.GetLength())); -} - -CFX_ByteString::CFX_ByteString(const CFX_ByteStringC& str1, - const CFX_ByteStringC& str2) { - FX_SAFE_STRSIZE nSafeLen = str1.GetLength(); - nSafeLen += str2.GetLength(); - - FX_STRSIZE nNewLen = nSafeLen.ValueOrDie(); - if (nNewLen == 0) - return; - - m_pData.Reset(StringData::Create(nNewLen)); - m_pData->CopyContents(str1.unterminated_c_str(), str1.GetLength()); - m_pData->CopyContentsAt(str1.GetLength(), str2.unterminated_c_str(), - str2.GetLength()); -} - -CFX_ByteString::CFX_ByteString( - const std::initializer_list& list) { - FX_SAFE_STRSIZE nSafeLen = 0; - for (const auto& item : list) - nSafeLen += item.GetLength(); - - FX_STRSIZE nNewLen = nSafeLen.ValueOrDie(); - if (nNewLen == 0) - return; - - m_pData.Reset(StringData::Create(nNewLen)); - - FX_STRSIZE nOffset = 0; - for (const auto& item : list) { - m_pData->CopyContentsAt(nOffset, item.unterminated_c_str(), - item.GetLength()); - nOffset += item.GetLength(); - } -} - -CFX_ByteString::CFX_ByteString(const std::ostringstream& outStream) { - std::string str = outStream.str(); - if (str.length() > 0) - m_pData.Reset(StringData::Create(str.c_str(), str.length())); -} - -CFX_ByteString::~CFX_ByteString() {} - -const CFX_ByteString& CFX_ByteString::operator=(const char* pStr) { - if (!pStr || !pStr[0]) - clear(); - else - AssignCopy(pStr, FXSYS_strlen(pStr)); - - return *this; -} - -const CFX_ByteString& CFX_ByteString::operator=( - const CFX_ByteStringC& stringSrc) { - if (stringSrc.IsEmpty()) - clear(); - else - AssignCopy(stringSrc.unterminated_c_str(), stringSrc.GetLength()); - - return *this; -} - -const CFX_ByteString& CFX_ByteString::operator=( - const CFX_ByteString& stringSrc) { - if (m_pData != stringSrc.m_pData) - m_pData = stringSrc.m_pData; - - return *this; -} - -const CFX_ByteString& CFX_ByteString::operator+=(const char* pStr) { - if (pStr) - Concat(pStr, FXSYS_strlen(pStr)); - - return *this; -} - -const CFX_ByteString& CFX_ByteString::operator+=(char ch) { - Concat(&ch, 1); - return *this; -} - -const CFX_ByteString& CFX_ByteString::operator+=(const CFX_ByteString& str) { - if (str.m_pData) - Concat(str.m_pData->m_String, str.m_pData->m_nDataLength); - - return *this; -} - -const CFX_ByteString& CFX_ByteString::operator+=(const CFX_ByteStringC& str) { - if (!str.IsEmpty()) - Concat(str.unterminated_c_str(), str.GetLength()); - - return *this; -} - -bool CFX_ByteString::operator==(const char* ptr) const { - if (!m_pData) - return !ptr || !ptr[0]; - - if (!ptr) - return m_pData->m_nDataLength == 0; - - return FXSYS_strlen(ptr) == m_pData->m_nDataLength && - memcmp(ptr, m_pData->m_String, m_pData->m_nDataLength) == 0; -} - -bool CFX_ByteString::operator==(const CFX_ByteStringC& str) const { - if (!m_pData) - return str.IsEmpty(); - - return m_pData->m_nDataLength == str.GetLength() && - memcmp(m_pData->m_String, str.unterminated_c_str(), str.GetLength()) == - 0; -} - -bool CFX_ByteString::operator==(const CFX_ByteString& other) const { - if (m_pData == other.m_pData) - return true; - - if (IsEmpty()) - return other.IsEmpty(); - - if (other.IsEmpty()) - return false; - - return other.m_pData->m_nDataLength == m_pData->m_nDataLength && - memcmp(other.m_pData->m_String, m_pData->m_String, - m_pData->m_nDataLength) == 0; -} - -bool CFX_ByteString::operator<(const CFX_ByteString& str) const { - if (m_pData == str.m_pData) - return false; - - int result = - memcmp(c_str(), str.c_str(), std::min(GetLength(), str.GetLength())); - return result < 0 || (result == 0 && GetLength() < str.GetLength()); -} - -bool CFX_ByteString::EqualNoCase(const CFX_ByteStringC& str) const { - if (!m_pData) - return str.IsEmpty(); - - FX_STRSIZE len = str.GetLength(); - if (m_pData->m_nDataLength != len) - return false; - - const uint8_t* pThis = (const uint8_t*)m_pData->m_String; - const uint8_t* pThat = str.raw_str(); - for (FX_STRSIZE i = 0; i < len; i++) { - if ((*pThis) != (*pThat)) { - uint8_t bThis = FXSYS_tolower(*pThis); - uint8_t bThat = FXSYS_tolower(*pThat); - if (bThis != bThat) - return false; - } - pThis++; - pThat++; - } - return true; -} - -void CFX_ByteString::AssignCopy(const char* pSrcData, FX_STRSIZE nSrcLen) { - AllocBeforeWrite(nSrcLen); - m_pData->CopyContents(pSrcData, nSrcLen); - m_pData->m_nDataLength = nSrcLen; -} - -void CFX_ByteString::ReallocBeforeWrite(FX_STRSIZE nNewLength) { - if (m_pData && m_pData->CanOperateInPlace(nNewLength)) - return; - - if (nNewLength == 0) { - clear(); - return; - } - - CFX_RetainPtr pNewData(StringData::Create(nNewLength)); - if (m_pData) { - FX_STRSIZE nCopyLength = std::min(m_pData->m_nDataLength, nNewLength); - pNewData->CopyContents(m_pData->m_String, nCopyLength); - pNewData->m_nDataLength = nCopyLength; - } else { - pNewData->m_nDataLength = 0; - } - pNewData->m_String[pNewData->m_nDataLength] = 0; - m_pData.Swap(pNewData); -} - -void CFX_ByteString::AllocBeforeWrite(FX_STRSIZE nNewLength) { - if (m_pData && m_pData->CanOperateInPlace(nNewLength)) - return; - - if (nNewLength == 0) { - clear(); - return; - } - - m_pData.Reset(StringData::Create(nNewLength)); -} - -void CFX_ByteString::ReleaseBuffer(FX_STRSIZE nNewLength) { - if (!m_pData) - return; - - nNewLength = std::min(nNewLength, m_pData->m_nAllocLength); - if (nNewLength == 0) { - clear(); - return; - } - - ASSERT(m_pData->m_nRefs == 1); - m_pData->m_nDataLength = nNewLength; - m_pData->m_String[nNewLength] = 0; - if (m_pData->m_nAllocLength - nNewLength >= 32) { - // Over arbitrary threshold, so pay the price to relocate. Force copy to - // always occur by holding a second reference to the string. - CFX_ByteString preserve(*this); - ReallocBeforeWrite(nNewLength); - } -} - -void CFX_ByteString::Reserve(FX_STRSIZE len) { - GetBuffer(len); -} - -char* CFX_ByteString::GetBuffer(FX_STRSIZE nMinBufLength) { - if (!m_pData) { - if (nMinBufLength == 0) - return nullptr; - - m_pData.Reset(StringData::Create(nMinBufLength)); - m_pData->m_nDataLength = 0; - m_pData->m_String[0] = 0; - return m_pData->m_String; - } - - if (m_pData->CanOperateInPlace(nMinBufLength)) - return m_pData->m_String; - - nMinBufLength = std::max(nMinBufLength, m_pData->m_nDataLength); - if (nMinBufLength == 0) - return nullptr; - - CFX_RetainPtr pNewData(StringData::Create(nMinBufLength)); - pNewData->CopyContents(*m_pData); - pNewData->m_nDataLength = m_pData->m_nDataLength; - m_pData.Swap(pNewData); - return m_pData->m_String; -} - -FX_STRSIZE CFX_ByteString::Delete(FX_STRSIZE index, FX_STRSIZE count) { - if (!m_pData) - return 0; - - FX_STRSIZE old_length = m_pData->m_nDataLength; - if (count == 0 || - index != pdfium::clamp(index, static_cast(0), old_length)) - return old_length; - - FX_STRSIZE removal_length = index + count; - if (removal_length > old_length) - return old_length; - - ReallocBeforeWrite(old_length); - FX_STRSIZE chars_to_copy = old_length - removal_length + 1; - memmove(m_pData->m_String + index, m_pData->m_String + removal_length, - chars_to_copy); - m_pData->m_nDataLength = old_length - count; - return m_pData->m_nDataLength; -} - -void CFX_ByteString::Concat(const char* pSrcData, FX_STRSIZE nSrcLen) { - if (!pSrcData || nSrcLen == 0) - return; - - if (!m_pData) { - m_pData.Reset(StringData::Create(pSrcData, nSrcLen)); - return; - } - - if (m_pData->CanOperateInPlace(m_pData->m_nDataLength + nSrcLen)) { - m_pData->CopyContentsAt(m_pData->m_nDataLength, pSrcData, nSrcLen); - m_pData->m_nDataLength += nSrcLen; - return; - } - - CFX_RetainPtr pNewData( - StringData::Create(m_pData->m_nDataLength + nSrcLen)); - pNewData->CopyContents(*m_pData); - pNewData->CopyContentsAt(m_pData->m_nDataLength, pSrcData, nSrcLen); - m_pData.Swap(pNewData); -} - -CFX_ByteString CFX_ByteString::Mid(FX_STRSIZE first, FX_STRSIZE count) const { - if (!m_pData) - return CFX_ByteString(); - - if (!IsValidIndex(first)) - return CFX_ByteString(); - - if (count == 0 || !IsValidLength(count)) - return CFX_ByteString(); - - if (!IsValidIndex(first + count - 1)) - return CFX_ByteString(); - - if (first == 0 && count == m_pData->m_nDataLength) - return *this; - - CFX_ByteString dest; - AllocCopy(dest, count, first); - return dest; -} - -CFX_ByteString CFX_ByteString::Left(FX_STRSIZE count) const { - if (count == 0 || !IsValidLength(count)) - return CFX_ByteString(); - return Mid(0, count); -} - -CFX_ByteString CFX_ByteString::Right(FX_STRSIZE count) const { - if (count == 0 || !IsValidLength(count)) - return CFX_ByteString(); - return Mid(GetLength() - count, count); -} - -void CFX_ByteString::AllocCopy(CFX_ByteString& dest, - FX_STRSIZE nCopyLen, - FX_STRSIZE nCopyIndex) const { - if (nCopyLen == 0) - return; - - CFX_RetainPtr pNewData( - StringData::Create(m_pData->m_String + nCopyIndex, nCopyLen)); - dest.m_pData.Swap(pNewData); -} - -#define FORCE_ANSI 0x10000 -#define FORCE_UNICODE 0x20000 -#define FORCE_INT64 0x40000 - -CFX_ByteString CFX_ByteString::FormatInteger(int i) { - char buf[32]; - FXSYS_snprintf(buf, 32, "%d", i); - return CFX_ByteString(buf); -} - -void CFX_ByteString::FormatV(const char* pFormat, va_list argList) { - va_list argListCopy; - va_copy(argListCopy, argList); - FX_STRSIZE nMaxLen = vsnprintf(nullptr, 0, pFormat, argListCopy); - va_end(argListCopy); - if (nMaxLen > 0) { - GetBuffer(nMaxLen); - if (m_pData) { - // In the following two calls, there's always space in the buffer for - // a terminating NUL that's not included in nMaxLen. - memset(m_pData->m_String, 0, nMaxLen + 1); - va_copy(argListCopy, argList); - vsnprintf(m_pData->m_String, nMaxLen + 1, pFormat, argListCopy); - va_end(argListCopy); - ReleaseBuffer(GetStringLength()); - } - } -} - -void CFX_ByteString::Format(const char* pFormat, ...) { - va_list argList; - va_start(argList, pFormat); - FormatV(pFormat, argList); - va_end(argList); -} - -void CFX_ByteString::SetAt(FX_STRSIZE index, char c) { - ASSERT(IsValidIndex(index)); - ReallocBeforeWrite(m_pData->m_nDataLength); - m_pData->m_String[index] = c; -} - -FX_STRSIZE CFX_ByteString::Insert(FX_STRSIZE location, char ch) { - const FX_STRSIZE cur_length = m_pData ? m_pData->m_nDataLength : 0; - if (!IsValidLength(location)) - return cur_length; - - const FX_STRSIZE new_length = cur_length + 1; - ReallocBeforeWrite(new_length); - memmove(m_pData->m_String + location + 1, m_pData->m_String + location, - new_length - location); - m_pData->m_String[location] = ch; - m_pData->m_nDataLength = new_length; - return new_length; -} - -pdfium::Optional CFX_ByteString::Find(char ch, - FX_STRSIZE start) const { - if (!m_pData) - return pdfium::Optional(); - - if (!IsValidIndex(start)) - return pdfium::Optional(); - - const char* pStr = static_cast( - memchr(m_pData->m_String + start, ch, m_pData->m_nDataLength - start)); - return pStr ? pdfium::Optional( - static_cast(pStr - m_pData->m_String)) - : pdfium::Optional(); -} - -pdfium::Optional CFX_ByteString::Find(const CFX_ByteStringC& subStr, - FX_STRSIZE start) const { - if (!m_pData) - return pdfium::Optional(); - - if (!IsValidIndex(start)) - return pdfium::Optional(); - - const char* pStr = - FX_strstr(m_pData->m_String + start, m_pData->m_nDataLength - start, - subStr.unterminated_c_str(), subStr.GetLength()); - return pStr ? pdfium::Optional( - static_cast(pStr - m_pData->m_String)) - : pdfium::Optional(); -} - -pdfium::Optional CFX_ByteString::ReverseFind(char ch) const { - if (!m_pData) - return pdfium::Optional(); - - FX_STRSIZE nLength = m_pData->m_nDataLength; - while (nLength--) { - if (m_pData->m_String[nLength] == ch) - return pdfium::Optional(nLength); - } - return pdfium::Optional(); -} - -void CFX_ByteString::MakeLower() { - if (!m_pData) - return; - - ReallocBeforeWrite(m_pData->m_nDataLength); - FXSYS_strlwr(m_pData->m_String); -} - -void CFX_ByteString::MakeUpper() { - if (!m_pData) - return; - - ReallocBeforeWrite(m_pData->m_nDataLength); - FXSYS_strupr(m_pData->m_String); -} - -FX_STRSIZE CFX_ByteString::Remove(char chRemove) { - if (!m_pData || m_pData->m_nDataLength < 1) - return 0; - - char* pstrSource = m_pData->m_String; - char* pstrEnd = m_pData->m_String + m_pData->m_nDataLength; - while (pstrSource < pstrEnd) { - if (*pstrSource == chRemove) - break; - pstrSource++; - } - if (pstrSource == pstrEnd) - return 0; - - ptrdiff_t copied = pstrSource - m_pData->m_String; - ReallocBeforeWrite(m_pData->m_nDataLength); - pstrSource = m_pData->m_String + copied; - pstrEnd = m_pData->m_String + m_pData->m_nDataLength; - - char* pstrDest = pstrSource; - while (pstrSource < pstrEnd) { - if (*pstrSource != chRemove) { - *pstrDest = *pstrSource; - pstrDest++; - } - pstrSource++; - } - - *pstrDest = 0; - FX_STRSIZE nCount = static_cast(pstrSource - pstrDest); - m_pData->m_nDataLength -= nCount; - return nCount; -} - -FX_STRSIZE CFX_ByteString::Replace(const CFX_ByteStringC& pOld, - const CFX_ByteStringC& pNew) { - if (!m_pData || pOld.IsEmpty()) - return 0; - - FX_STRSIZE nSourceLen = pOld.GetLength(); - FX_STRSIZE nReplacementLen = pNew.GetLength(); - FX_STRSIZE nCount = 0; - const char* pStart = m_pData->m_String; - char* pEnd = m_pData->m_String + m_pData->m_nDataLength; - while (1) { - const char* pTarget = FX_strstr(pStart, static_cast(pEnd - pStart), - pOld.unterminated_c_str(), nSourceLen); - if (!pTarget) - break; - - nCount++; - pStart = pTarget + nSourceLen; - } - if (nCount == 0) - return 0; - - FX_STRSIZE nNewLength = - m_pData->m_nDataLength + (nReplacementLen - nSourceLen) * nCount; - - if (nNewLength == 0) { - clear(); - return nCount; - } - - CFX_RetainPtr pNewData(StringData::Create(nNewLength)); - pStart = m_pData->m_String; - char* pDest = pNewData->m_String; - for (FX_STRSIZE i = 0; i < nCount; i++) { - const char* pTarget = FX_strstr(pStart, static_cast(pEnd - pStart), - pOld.unterminated_c_str(), nSourceLen); - memcpy(pDest, pStart, pTarget - pStart); - pDest += pTarget - pStart; - memcpy(pDest, pNew.unterminated_c_str(), pNew.GetLength()); - pDest += pNew.GetLength(); - pStart = pTarget + nSourceLen; - } - memcpy(pDest, pStart, pEnd - pStart); - m_pData.Swap(pNewData); - return nCount; -} - -CFX_WideString CFX_ByteString::UTF8Decode() const { - CFX_UTF8Decoder decoder; - for (FX_STRSIZE i = 0; i < GetLength(); i++) { - decoder.Input(static_cast(m_pData->m_String[i])); - } - return CFX_WideString(decoder.GetResult()); -} - -// static -CFX_ByteString CFX_ByteString::FromUnicode(const CFX_WideString& str) { - return GetByteString(0, str.AsStringC()); -} - -int CFX_ByteString::Compare(const CFX_ByteStringC& str) const { - if (!m_pData) { - return str.IsEmpty() ? 0 : -1; - } - FX_STRSIZE this_len = m_pData->m_nDataLength; - FX_STRSIZE that_len = str.GetLength(); - FX_STRSIZE min_len = std::min(this_len, that_len); - for (FX_STRSIZE i = 0; i < min_len; i++) { - if (static_cast(m_pData->m_String[i]) < str[i]) { - return -1; - } - if (static_cast(m_pData->m_String[i]) > str[i]) { - return 1; - } - } - if (this_len < that_len) { - return -1; - } - if (this_len > that_len) { - return 1; - } - return 0; -} - -void CFX_ByteString::TrimRight(const CFX_ByteStringC& pTargets) { - if (!m_pData || pTargets.IsEmpty()) - return; - - FX_STRSIZE pos = GetLength(); - if (pos == 0) - return; - - while (pos) { - FX_STRSIZE i = 0; - while (i < pTargets.GetLength() && - pTargets[i] != m_pData->m_String[pos - 1]) { - i++; - } - if (i == pTargets.GetLength()) { - break; - } - pos--; - } - if (pos < m_pData->m_nDataLength) { - ReallocBeforeWrite(m_pData->m_nDataLength); - m_pData->m_String[pos] = 0; - m_pData->m_nDataLength = pos; - } -} - -void CFX_ByteString::TrimRight(char chTarget) { - TrimRight(CFX_ByteStringC(chTarget)); -} - -void CFX_ByteString::TrimRight() { - TrimRight("\x09\x0a\x0b\x0c\x0d\x20"); -} - -void CFX_ByteString::TrimLeft(const CFX_ByteStringC& pTargets) { - if (!m_pData || pTargets.IsEmpty()) - return; - - FX_STRSIZE len = GetLength(); - if (len == 0) - return; - - FX_STRSIZE pos = 0; - while (pos < len) { - FX_STRSIZE i = 0; - while (i < pTargets.GetLength() && pTargets[i] != m_pData->m_String[pos]) { - i++; - } - if (i == pTargets.GetLength()) { - break; - } - pos++; - } - if (pos) { - ReallocBeforeWrite(len); - FX_STRSIZE nDataLength = len - pos; - memmove(m_pData->m_String, m_pData->m_String + pos, - (nDataLength + 1) * sizeof(char)); - m_pData->m_nDataLength = nDataLength; - } -} - -void CFX_ByteString::TrimLeft(char chTarget) { - TrimLeft(CFX_ByteStringC(chTarget)); -} - -void CFX_ByteString::TrimLeft() { - TrimLeft("\x09\x0a\x0b\x0c\x0d\x20"); -} - -CFX_ByteString CFX_ByteString::FormatFloat(float d, int precision) { - char buf[32]; - FX_STRSIZE len = FX_ftoa(d, buf); - return CFX_ByteString(buf, len); -} - -std::ostream& operator<<(std::ostream& os, const CFX_ByteString& str) { - return os.write(str.c_str(), str.GetLength()); -} - -std::ostream& operator<<(std::ostream& os, const CFX_ByteStringC& str) { - return os.write(str.unterminated_c_str(), str.GetLength()); -} diff --git a/core/fxcrt/cfx_bytestring.h b/core/fxcrt/cfx_bytestring.h deleted file mode 100644 index b976287617..0000000000 --- a/core/fxcrt/cfx_bytestring.h +++ /dev/null @@ -1,273 +0,0 @@ -// Copyright 2017 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef CORE_FXCRT_CFX_BYTESTRING_H_ -#define CORE_FXCRT_CFX_BYTESTRING_H_ - -#include -#include -#include -#include - -#include "core/fxcrt/cfx_retain_ptr.h" -#include "core/fxcrt/cfx_string_c_template.h" -#include "core/fxcrt/cfx_string_data_template.h" -#include "core/fxcrt/fx_system.h" -#include "third_party/base/optional.h" - -class CFX_WideString; - -// A mutable string with shared buffers using copy-on-write semantics that -// avoids the cost of std::string's iterator stability guarantees. -class CFX_ByteString { - public: - using CharType = char; - using const_iterator = const CharType*; - using const_reverse_iterator = std::reverse_iterator; - - CFX_ByteString(); - CFX_ByteString(const CFX_ByteString& other); - CFX_ByteString(CFX_ByteString&& other) noexcept; - - // Deliberately implicit to avoid calling on every string literal. - // NOLINTNEXTLINE(runtime/explicit) - CFX_ByteString(char ch); - // NOLINTNEXTLINE(runtime/explicit) - CFX_ByteString(const char* ptr); - - // No implicit conversions from wide strings. - // NOLINTNEXTLINE(runtime/explicit) - CFX_ByteString(wchar_t) = delete; - - CFX_ByteString(const char* ptr, FX_STRSIZE len); - CFX_ByteString(const uint8_t* ptr, FX_STRSIZE len); - - explicit CFX_ByteString(const CFX_ByteStringC& bstrc); - CFX_ByteString(const CFX_ByteStringC& bstrc1, const CFX_ByteStringC& bstrc2); - CFX_ByteString(const std::initializer_list& list); - explicit CFX_ByteString(const std::ostringstream& outStream); - - ~CFX_ByteString(); - - void clear() { m_pData.Reset(); } - - static CFX_ByteString FromUnicode(const CFX_WideString& str); - - // Explicit conversion to C-style string. - // Note: Any subsequent modification of |this| will invalidate the result. - const char* c_str() const { return m_pData ? m_pData->m_String : ""; } - - // Explicit conversion to uint8_t*. - // Note: Any subsequent modification of |this| will invalidate the result. - const uint8_t* raw_str() const { - return m_pData ? reinterpret_cast(m_pData->m_String) - : nullptr; - } - - // Explicit conversion to CFX_ByteStringC. - // Note: Any subsequent modification of |this| will invalidate the result. - CFX_ByteStringC AsStringC() const { - return CFX_ByteStringC(raw_str(), GetLength()); - } - - // Note: Any subsequent modification of |this| will invalidate iterators. - const_iterator begin() const { return m_pData ? m_pData->m_String : nullptr; } - const_iterator end() const { - return m_pData ? m_pData->m_String + m_pData->m_nDataLength : nullptr; - } - - // Note: Any subsequent modification of |this| will invalidate iterators. - const_reverse_iterator rbegin() const { - return const_reverse_iterator(end()); - } - const_reverse_iterator rend() const { - return const_reverse_iterator(begin()); - } - - FX_STRSIZE GetLength() const { return m_pData ? m_pData->m_nDataLength : 0; } - FX_STRSIZE GetStringLength() const { - return m_pData ? FXSYS_strlen(m_pData->m_String) : 0; - } - bool IsEmpty() const { return !GetLength(); } - bool IsValidIndex(FX_STRSIZE index) const { return index < GetLength(); } - bool IsValidLength(FX_STRSIZE length) const { return length <= GetLength(); } - - int Compare(const CFX_ByteStringC& str) const; - bool EqualNoCase(const CFX_ByteStringC& str) const; - - bool operator==(const char* ptr) const; - bool operator==(const CFX_ByteStringC& str) const; - bool operator==(const CFX_ByteString& other) const; - - bool operator!=(const char* ptr) const { return !(*this == ptr); } - bool operator!=(const CFX_ByteStringC& str) const { return !(*this == str); } - bool operator!=(const CFX_ByteString& other) const { - return !(*this == other); - } - - bool operator<(const CFX_ByteString& str) const; - - const CFX_ByteString& operator=(const char* str); - const CFX_ByteString& operator=(const CFX_ByteStringC& bstrc); - const CFX_ByteString& operator=(const CFX_ByteString& stringSrc); - - const CFX_ByteString& operator+=(char ch); - const CFX_ByteString& operator+=(const char* str); - const CFX_ByteString& operator+=(const CFX_ByteString& str); - const CFX_ByteString& operator+=(const CFX_ByteStringC& bstrc); - - CharType operator[](const FX_STRSIZE index) const { - ASSERT(IsValidIndex(index)); - return m_pData ? m_pData->m_String[index] : 0; - } - - CharType First() const { return GetLength() ? (*this)[0] : 0; } - CharType Last() const { return GetLength() ? (*this)[GetLength() - 1] : 0; } - - void SetAt(FX_STRSIZE index, char c); - - FX_STRSIZE Insert(FX_STRSIZE index, char ch); - FX_STRSIZE InsertAtFront(char ch) { return Insert(0, ch); } - FX_STRSIZE InsertAtBack(char ch) { return Insert(GetLength(), ch); } - FX_STRSIZE Delete(FX_STRSIZE index, FX_STRSIZE count = 1); - - void Format(const char* lpszFormat, ...); - void FormatV(const char* lpszFormat, va_list argList); - - void Reserve(FX_STRSIZE len); - char* GetBuffer(FX_STRSIZE len); - void ReleaseBuffer(FX_STRSIZE len); - - CFX_ByteString Mid(FX_STRSIZE first, FX_STRSIZE count) const; - CFX_ByteString Left(FX_STRSIZE count) const; - CFX_ByteString Right(FX_STRSIZE count) const; - - pdfium::Optional Find(const CFX_ByteStringC& lpszSub, - FX_STRSIZE start = 0) const; - pdfium::Optional Find(char ch, FX_STRSIZE start = 0) const; - pdfium::Optional ReverseFind(char ch) const; - - bool Contains(const CFX_ByteStringC& lpszSub, FX_STRSIZE start = 0) const { - return Find(lpszSub, start).has_value(); - } - - bool Contains(char ch, FX_STRSIZE start = 0) const { - return Find(ch, start).has_value(); - } - - void MakeLower(); - void MakeUpper(); - - void TrimRight(); - void TrimRight(char chTarget); - void TrimRight(const CFX_ByteStringC& lpszTargets); - - void TrimLeft(); - void TrimLeft(char chTarget); - void TrimLeft(const CFX_ByteStringC& lpszTargets); - - FX_STRSIZE Replace(const CFX_ByteStringC& lpszOld, - const CFX_ByteStringC& lpszNew); - - FX_STRSIZE Remove(char ch); - - CFX_WideString UTF8Decode() const; - - uint32_t GetID() const { return AsStringC().GetID(); } - - static CFX_ByteString FormatInteger(int i); - static CFX_ByteString FormatFloat(float f, int precision = 0); - - protected: - using StringData = CFX_StringDataTemplate; - - void ReallocBeforeWrite(FX_STRSIZE nNewLen); - void AllocBeforeWrite(FX_STRSIZE nNewLen); - void AllocCopy(CFX_ByteString& dest, - FX_STRSIZE nCopyLen, - FX_STRSIZE nCopyIndex) const; - void AssignCopy(const char* pSrcData, FX_STRSIZE nSrcLen); - void Concat(const char* lpszSrcData, FX_STRSIZE nSrcLen); - - CFX_RetainPtr m_pData; - - friend class fxcrt_ByteStringConcat_Test; - friend class fxcrt_ByteStringPool_Test; -}; - -inline bool operator==(const char* lhs, const CFX_ByteString& rhs) { - return rhs == lhs; -} -inline bool operator==(const CFX_ByteStringC& lhs, const CFX_ByteString& rhs) { - return rhs == lhs; -} -inline bool operator!=(const char* lhs, const CFX_ByteString& rhs) { - return rhs != lhs; -} -inline bool operator!=(const CFX_ByteStringC& lhs, const CFX_ByteString& rhs) { - return rhs != lhs; -} - -inline CFX_ByteString operator+(const CFX_ByteStringC& str1, - const CFX_ByteStringC& str2) { - return CFX_ByteString(str1, str2); -} -inline CFX_ByteString operator+(const CFX_ByteStringC& str1, const char* str2) { - return CFX_ByteString(str1, str2); -} -inline CFX_ByteString operator+(const char* str1, const CFX_ByteStringC& str2) { - return CFX_ByteString(str1, str2); -} -inline CFX_ByteString operator+(const CFX_ByteStringC& str1, char ch) { - return CFX_ByteString(str1, CFX_ByteStringC(ch)); -} -inline CFX_ByteString operator+(char ch, const CFX_ByteStringC& str2) { - return CFX_ByteString(ch, str2); -} -inline CFX_ByteString operator+(const CFX_ByteString& str1, - const CFX_ByteString& str2) { - return CFX_ByteString(str1.AsStringC(), str2.AsStringC()); -} -inline CFX_ByteString operator+(const CFX_ByteString& str1, char ch) { - return CFX_ByteString(str1.AsStringC(), CFX_ByteStringC(ch)); -} -inline CFX_ByteString operator+(char ch, const CFX_ByteString& str2) { - return CFX_ByteString(ch, str2.AsStringC()); -} -inline CFX_ByteString operator+(const CFX_ByteString& str1, const char* str2) { - return CFX_ByteString(str1.AsStringC(), str2); -} -inline CFX_ByteString operator+(const char* str1, const CFX_ByteString& str2) { - return CFX_ByteString(str1, str2.AsStringC()); -} -inline CFX_ByteString operator+(const CFX_ByteString& str1, - const CFX_ByteStringC& str2) { - return CFX_ByteString(str1.AsStringC(), str2); -} -inline CFX_ByteString operator+(const CFX_ByteStringC& str1, - const CFX_ByteString& str2) { - return CFX_ByteString(str1, str2.AsStringC()); -} - -uint32_t FX_HashCode_GetA(const CFX_ByteStringC& str, bool bIgnoreCase); - -std::ostream& operator<<(std::ostream& os, const CFX_ByteString& str); -std::ostream& operator<<(std::ostream& os, const CFX_ByteStringC& str); - -namespace std { - -template <> -struct hash { - std::size_t operator()(const CFX_ByteString& str) const { - return FX_HashCode_GetA(str.AsStringC(), false); - } -}; - -} // namespace std - -extern template struct std::hash; - -#endif // CORE_FXCRT_CFX_BYTESTRING_H_ diff --git a/core/fxcrt/cfx_bytestring_unittest.cpp b/core/fxcrt/cfx_bytestring_unittest.cpp deleted file mode 100644 index 6bbe305268..0000000000 --- a/core/fxcrt/cfx_bytestring_unittest.cpp +++ /dev/null @@ -1,1642 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "core/fxcrt/cfx_bytestring.h" -#include "core/fxcrt/fx_string.h" - -#include -#include - -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/base/stl_util.h" - -TEST(fxcrt, ByteStringElementAccess) { - const CFX_ByteString abc("abc"); - EXPECT_EQ('a', abc[0]); - EXPECT_EQ('b', abc[1]); - EXPECT_EQ('c', abc[2]); -#ifndef NDEBUG - EXPECT_DEATH({ abc[3]; }, ".*"); -#endif - - CFX_ByteString mutable_abc = abc; - EXPECT_EQ(abc.c_str(), mutable_abc.c_str()); - EXPECT_EQ('a', mutable_abc[0]); - EXPECT_EQ('b', mutable_abc[1]); - EXPECT_EQ('c', mutable_abc[2]); - EXPECT_EQ(abc.c_str(), mutable_abc.c_str()); - EXPECT_EQ("abc", abc); - - const char* c_str = abc.c_str(); - mutable_abc.SetAt(0, 'd'); - EXPECT_EQ(c_str, abc.c_str()); - EXPECT_NE(c_str, mutable_abc.c_str()); - EXPECT_EQ("abc", abc); - EXPECT_EQ("dbc", mutable_abc); - - mutable_abc.SetAt(1, 'e'); - EXPECT_EQ("abc", abc); - EXPECT_EQ("dec", mutable_abc); - - mutable_abc.SetAt(2, 'f'); - EXPECT_EQ("abc", abc); - EXPECT_EQ("def", mutable_abc); -#ifndef NDEBUG - EXPECT_DEATH({ mutable_abc.SetAt(3, 'g'); }, ".*"); - EXPECT_EQ("abc", abc); -#endif -} - -TEST(fxcrt, ByteStringOperatorLT) { - CFX_ByteString empty; - CFX_ByteString a("a"); - CFX_ByteString abc("abc"); - CFX_ByteString def("def"); - - EXPECT_FALSE(empty < empty); - EXPECT_FALSE(a < a); - EXPECT_FALSE(abc < abc); - EXPECT_FALSE(def < def); - - EXPECT_TRUE(empty < a); - EXPECT_FALSE(a < empty); - - EXPECT_TRUE(empty < abc); - EXPECT_FALSE(abc < empty); - - EXPECT_TRUE(empty < def); - EXPECT_FALSE(def < empty); - - EXPECT_TRUE(a < abc); - EXPECT_FALSE(abc < a); - - EXPECT_TRUE(a < def); - EXPECT_FALSE(def < a); - - EXPECT_TRUE(abc < def); - EXPECT_FALSE(def < abc); -} - -TEST(fxcrt, ByteStringOperatorEQ) { - CFX_ByteString null_string; - EXPECT_TRUE(null_string == null_string); - - CFX_ByteString empty_string(""); - EXPECT_TRUE(empty_string == empty_string); - EXPECT_TRUE(empty_string == null_string); - EXPECT_TRUE(null_string == empty_string); - - CFX_ByteString deleted_string("hello"); - deleted_string.Delete(0, 5); - EXPECT_TRUE(deleted_string == deleted_string); - EXPECT_TRUE(deleted_string == null_string); - EXPECT_TRUE(deleted_string == empty_string); - EXPECT_TRUE(null_string == deleted_string); - EXPECT_TRUE(empty_string == deleted_string); - - CFX_ByteString byte_string("hello"); - EXPECT_TRUE(byte_string == byte_string); - EXPECT_FALSE(byte_string == null_string); - EXPECT_FALSE(byte_string == empty_string); - EXPECT_FALSE(byte_string == deleted_string); - EXPECT_FALSE(null_string == byte_string); - EXPECT_FALSE(empty_string == byte_string); - EXPECT_FALSE(deleted_string == byte_string); - - CFX_ByteString byte_string_same1("hello"); - EXPECT_TRUE(byte_string == byte_string_same1); - EXPECT_TRUE(byte_string_same1 == byte_string); - - CFX_ByteString byte_string_same2(byte_string); - EXPECT_TRUE(byte_string == byte_string_same2); - EXPECT_TRUE(byte_string_same2 == byte_string); - - CFX_ByteString byte_string1("he"); - CFX_ByteString byte_string2("hellp"); - CFX_ByteString byte_string3("hellod"); - EXPECT_FALSE(byte_string == byte_string1); - EXPECT_FALSE(byte_string == byte_string2); - EXPECT_FALSE(byte_string == byte_string3); - EXPECT_FALSE(byte_string1 == byte_string); - EXPECT_FALSE(byte_string2 == byte_string); - EXPECT_FALSE(byte_string3 == byte_string); - - CFX_ByteStringC null_string_c; - CFX_ByteStringC empty_string_c(""); - EXPECT_TRUE(null_string == null_string_c); - EXPECT_TRUE(null_string == empty_string_c); - EXPECT_TRUE(empty_string == null_string_c); - EXPECT_TRUE(empty_string == empty_string_c); - EXPECT_TRUE(deleted_string == null_string_c); - EXPECT_TRUE(deleted_string == empty_string_c); - EXPECT_TRUE(null_string_c == null_string); - EXPECT_TRUE(empty_string_c == null_string); - EXPECT_TRUE(null_string_c == empty_string); - EXPECT_TRUE(empty_string_c == empty_string); - EXPECT_TRUE(null_string_c == deleted_string); - EXPECT_TRUE(empty_string_c == deleted_string); - - CFX_ByteStringC byte_string_c_same1("hello"); - EXPECT_TRUE(byte_string == byte_string_c_same1); - EXPECT_TRUE(byte_string_c_same1 == byte_string); - - CFX_ByteStringC byte_string_c1("he"); - CFX_ByteStringC byte_string_c2("hellp"); - CFX_ByteStringC byte_string_c3("hellod"); - EXPECT_FALSE(byte_string == byte_string_c1); - EXPECT_FALSE(byte_string == byte_string_c2); - EXPECT_FALSE(byte_string == byte_string_c3); - EXPECT_FALSE(byte_string_c1 == byte_string); - EXPECT_FALSE(byte_string_c2 == byte_string); - EXPECT_FALSE(byte_string_c3 == byte_string); - - const char* c_null_string = nullptr; - const char* c_empty_string = ""; - EXPECT_TRUE(null_string == c_null_string); - EXPECT_TRUE(null_string == c_empty_string); - EXPECT_TRUE(empty_string == c_null_string); - EXPECT_TRUE(empty_string == c_empty_string); - EXPECT_TRUE(deleted_string == c_null_string); - EXPECT_TRUE(deleted_string == c_empty_string); - EXPECT_TRUE(c_null_string == null_string); - EXPECT_TRUE(c_empty_string == null_string); - EXPECT_TRUE(c_null_string == empty_string); - EXPECT_TRUE(c_empty_string == empty_string); - EXPECT_TRUE(c_null_string == deleted_string); - EXPECT_TRUE(c_empty_string == deleted_string); - - const char* c_string_same1 = "hello"; - EXPECT_TRUE(byte_string == c_string_same1); - EXPECT_TRUE(c_string_same1 == byte_string); - - const char* c_string1 = "he"; - const char* c_string2 = "hellp"; - const char* c_string3 = "hellod"; - EXPECT_FALSE(byte_string == c_string1); - EXPECT_FALSE(byte_string == c_string2); - EXPECT_FALSE(byte_string == c_string3); - EXPECT_FALSE(c_string1 == byte_string); - EXPECT_FALSE(c_string2 == byte_string); - EXPECT_FALSE(c_string3 == byte_string); -} - -TEST(fxcrt, ByteStringOperatorNE) { - CFX_ByteString null_string; - EXPECT_FALSE(null_string != null_string); - - CFX_ByteString empty_string(""); - EXPECT_FALSE(empty_string != empty_string); - EXPECT_FALSE(empty_string != null_string); - EXPECT_FALSE(null_string != empty_string); - - CFX_ByteString deleted_string("hello"); - deleted_string.Delete(0, 5); - EXPECT_FALSE(deleted_string != deleted_string); - EXPECT_FALSE(deleted_string != null_string); - EXPECT_FALSE(deleted_string != empty_string); - EXPECT_FALSE(deleted_string != deleted_string); - EXPECT_FALSE(null_string != deleted_string); - EXPECT_FALSE(empty_string != deleted_string); - EXPECT_FALSE(deleted_string != deleted_string); - - CFX_ByteString byte_string("hello"); - EXPECT_FALSE(byte_string != byte_string); - EXPECT_TRUE(byte_string != null_string); - EXPECT_TRUE(byte_string != empty_string); - EXPECT_TRUE(byte_string != deleted_string); - EXPECT_TRUE(null_string != byte_string); - EXPECT_TRUE(empty_string != byte_string); - EXPECT_TRUE(deleted_string != byte_string); - - CFX_ByteString byte_string_same1("hello"); - EXPECT_FALSE(byte_string != byte_string_same1); - EXPECT_FALSE(byte_string_same1 != byte_string); - - CFX_ByteString byte_string_same2(byte_string); - EXPECT_FALSE(byte_string != byte_string_same2); - EXPECT_FALSE(byte_string_same2 != byte_string); - - CFX_ByteString byte_string1("he"); - CFX_ByteString byte_string2("hellp"); - CFX_ByteString byte_string3("hellod"); - EXPECT_TRUE(byte_string != byte_string1); - EXPECT_TRUE(byte_string != byte_string2); - EXPECT_TRUE(byte_string != byte_string3); - EXPECT_TRUE(byte_string1 != byte_string); - EXPECT_TRUE(byte_string2 != byte_string); - EXPECT_TRUE(byte_string3 != byte_string); - - CFX_ByteStringC null_string_c; - CFX_ByteStringC empty_string_c(""); - EXPECT_FALSE(null_string != null_string_c); - EXPECT_FALSE(null_string != empty_string_c); - EXPECT_FALSE(empty_string != null_string_c); - EXPECT_FALSE(empty_string != empty_string_c); - EXPECT_FALSE(null_string_c != null_string); - EXPECT_FALSE(empty_string_c != null_string); - EXPECT_FALSE(null_string_c != empty_string); - EXPECT_FALSE(empty_string_c != empty_string); - - CFX_ByteStringC byte_string_c_same1("hello"); - EXPECT_FALSE(byte_string != byte_string_c_same1); - EXPECT_FALSE(byte_string_c_same1 != byte_string); - - CFX_ByteStringC byte_string_c1("he"); - CFX_ByteStringC byte_string_c2("hellp"); - CFX_ByteStringC byte_string_c3("hellod"); - EXPECT_TRUE(byte_string != byte_string_c1); - EXPECT_TRUE(byte_string != byte_string_c2); - EXPECT_TRUE(byte_string != byte_string_c3); - EXPECT_TRUE(byte_string_c1 != byte_string); - EXPECT_TRUE(byte_string_c2 != byte_string); - EXPECT_TRUE(byte_string_c3 != byte_string); - - const char* c_null_string = nullptr; - const char* c_empty_string = ""; - EXPECT_FALSE(null_string != c_null_string); - EXPECT_FALSE(null_string != c_empty_string); - EXPECT_FALSE(empty_string != c_null_string); - EXPECT_FALSE(empty_string != c_empty_string); - EXPECT_FALSE(deleted_string != c_null_string); - EXPECT_FALSE(deleted_string != c_empty_string); - EXPECT_FALSE(c_null_string != null_string); - EXPECT_FALSE(c_empty_string != null_string); - EXPECT_FALSE(c_null_string != empty_string); - EXPECT_FALSE(c_empty_string != empty_string); - EXPECT_FALSE(c_null_string != deleted_string); - EXPECT_FALSE(c_empty_string != deleted_string); - - const char* c_string_same1 = "hello"; - EXPECT_FALSE(byte_string != c_string_same1); - EXPECT_FALSE(c_string_same1 != byte_string); - - const char* c_string1 = "he"; - const char* c_string2 = "hellp"; - const char* c_string3 = "hellod"; - EXPECT_TRUE(byte_string != c_string1); - EXPECT_TRUE(byte_string != c_string2); - EXPECT_TRUE(byte_string != c_string3); - EXPECT_TRUE(c_string1 != byte_string); - EXPECT_TRUE(c_string2 != byte_string); - EXPECT_TRUE(c_string3 != byte_string); -} - -TEST(fxcrt, ByteStringCNull) { - CFX_ByteStringC null_string; - EXPECT_FALSE(null_string.raw_str()); - EXPECT_EQ(0u, null_string.GetLength()); - EXPECT_TRUE(null_string.IsEmpty()); - - CFX_ByteStringC another_null_string; - EXPECT_EQ(null_string, another_null_string); - - CFX_ByteStringC copied_null_string(null_string); - EXPECT_FALSE(copied_null_string.raw_str()); - EXPECT_EQ(0u, copied_null_string.GetLength()); - EXPECT_TRUE(copied_null_string.IsEmpty()); - EXPECT_EQ(null_string, copied_null_string); - - CFX_ByteStringC empty_string(""); // Pointer to NUL, not NULL pointer. - EXPECT_TRUE(empty_string.raw_str()); - EXPECT_EQ(0u, empty_string.GetLength()); - EXPECT_TRUE(empty_string.IsEmpty()); - EXPECT_EQ(null_string, empty_string); - - CFX_ByteStringC assigned_null_string("initially not nullptr"); - assigned_null_string = null_string; - EXPECT_FALSE(assigned_null_string.raw_str()); - EXPECT_EQ(0u, assigned_null_string.GetLength()); - EXPECT_TRUE(assigned_null_string.IsEmpty()); - EXPECT_EQ(null_string, assigned_null_string); - - CFX_ByteStringC assigned_nullptr_string("initially not nullptr"); - assigned_nullptr_string = nullptr; - EXPECT_FALSE(assigned_nullptr_string.raw_str()); - EXPECT_EQ(0u, assigned_nullptr_string.GetLength()); - EXPECT_TRUE(assigned_nullptr_string.IsEmpty()); - EXPECT_EQ(null_string, assigned_nullptr_string); - - CFX_ByteStringC non_null_string("a"); - EXPECT_NE(null_string, non_null_string); -} - -TEST(fxcrt, ByteStringConcat) { - CFX_ByteString fred; - fred.Concat("FRED", 4); - EXPECT_EQ("FRED", fred); - - fred.Concat("DY", 2); - EXPECT_EQ("FREDDY", fred); - - fred.Delete(3, 3); - EXPECT_EQ("FRE", fred); - - fred.Concat("D", 1); - EXPECT_EQ("FRED", fred); - - CFX_ByteString copy = fred; - fred.Concat("DY", 2); - EXPECT_EQ("FREDDY", fred); - EXPECT_EQ("FRED", copy); -} - -TEST(fxcrt, ByteStringRemove) { - CFX_ByteString freed("FREED"); - freed.Remove('E'); - EXPECT_EQ("FRD", freed); - freed.Remove('F'); - EXPECT_EQ("RD", freed); - freed.Remove('D'); - EXPECT_EQ("R", freed); - freed.Remove('X'); - EXPECT_EQ("R", freed); - freed.Remove('R'); - EXPECT_EQ("", freed); - - CFX_ByteString empty; - empty.Remove('X'); - EXPECT_EQ("", empty); -} - -TEST(fxcrt, ByteStringRemoveCopies) { - CFX_ByteString freed("FREED"); - const char* old_buffer = freed.c_str(); - - // No change with single reference - no copy. - freed.Remove('Q'); - EXPECT_EQ("FREED", freed); - EXPECT_EQ(old_buffer, freed.c_str()); - - // Change with single reference - no copy. - freed.Remove('E'); - EXPECT_EQ("FRD", freed); - EXPECT_EQ(old_buffer, freed.c_str()); - - // No change with multiple references - no copy. - CFX_ByteString shared(freed); - freed.Remove('Q'); - EXPECT_EQ("FRD", freed); - EXPECT_EQ(old_buffer, freed.c_str()); - EXPECT_EQ(old_buffer, shared.c_str()); - - // Change with multiple references -- must copy. - freed.Remove('D'); - EXPECT_EQ("FR", freed); - EXPECT_NE(old_buffer, freed.c_str()); - EXPECT_EQ("FRD", shared); - EXPECT_EQ(old_buffer, shared.c_str()); -} - -TEST(fxcrt, ByteStringReplace) { - CFX_ByteString fred("FRED"); - fred.Replace("FR", "BL"); - EXPECT_EQ("BLED", fred); - fred.Replace("D", "DDY"); - EXPECT_EQ("BLEDDY", fred); - fred.Replace("LEDD", ""); - EXPECT_EQ("BY", fred); - fred.Replace("X", "CLAMS"); - EXPECT_EQ("BY", fred); - fred.Replace("BY", "HI"); - EXPECT_EQ("HI", fred); - fred.Replace("", "CLAMS"); - EXPECT_EQ("HI", fred); - fred.Replace("HI", ""); - EXPECT_EQ("", fred); -} - -TEST(fxcrt, ByteStringInsert) { - CFX_ByteString fred("FRED"); - EXPECT_EQ(5u, fred.Insert(0, 'S')); - EXPECT_EQ("SFRED", fred); - EXPECT_EQ(6u, fred.Insert(1, 'T')); - EXPECT_EQ("STFRED", fred); - EXPECT_EQ(7u, fred.Insert(4, 'U')); - EXPECT_EQ("STFRUED", fred); - EXPECT_EQ(8u, fred.Insert(7, 'V')); - EXPECT_EQ("STFRUEDV", fred); - EXPECT_EQ(8u, fred.Insert(12, 'P')); - EXPECT_EQ("STFRUEDV", fred); - { - CFX_ByteString empty; - EXPECT_EQ(1u, empty.Insert(0, 'X')); - EXPECT_EQ("X", empty); - } - { - CFX_ByteString empty; - EXPECT_EQ(0u, empty.Insert(5, 'X')); - EXPECT_NE("X", empty); - } -} - -TEST(fxcrt, ByteStringInsertAtFrontAndInsertAtBack) { - { - CFX_ByteString empty; - EXPECT_EQ(1u, empty.InsertAtFront('D')); - EXPECT_EQ("D", empty); - EXPECT_EQ(2u, empty.InsertAtFront('E')); - EXPECT_EQ("ED", empty); - EXPECT_EQ(3u, empty.InsertAtFront('R')); - EXPECT_EQ("RED", empty); - EXPECT_EQ(4u, empty.InsertAtFront('F')); - EXPECT_EQ("FRED", empty); - } - { - CFX_ByteString empty; - EXPECT_EQ(1u, empty.InsertAtBack('F')); - EXPECT_EQ("F", empty); - EXPECT_EQ(2u, empty.InsertAtBack('R')); - EXPECT_EQ("FR", empty); - EXPECT_EQ(3u, empty.InsertAtBack('E')); - EXPECT_EQ("FRE", empty); - EXPECT_EQ(4u, empty.InsertAtBack('D')); - EXPECT_EQ("FRED", empty); - } - { - CFX_ByteString empty; - EXPECT_EQ(1u, empty.InsertAtBack('E')); - EXPECT_EQ("E", empty); - EXPECT_EQ(2u, empty.InsertAtFront('R')); - EXPECT_EQ("RE", empty); - EXPECT_EQ(3u, empty.InsertAtBack('D')); - EXPECT_EQ("RED", empty); - EXPECT_EQ(4u, empty.InsertAtFront('F')); - EXPECT_EQ("FRED", empty); - } -} - -TEST(fxcrt, ByteStringDelete) { - CFX_ByteString fred("FRED"); - EXPECT_EQ(4u, fred.Delete(0, 0)); - EXPECT_EQ("FRED", fred); - EXPECT_EQ(2u, fred.Delete(0, 2)); - EXPECT_EQ("ED", fred); - EXPECT_EQ(1u, fred.Delete(1)); - EXPECT_EQ("E", fred); - EXPECT_EQ(0u, fred.Delete(0)); - EXPECT_EQ("", fred); - EXPECT_EQ(0u, fred.Delete(0)); - EXPECT_EQ("", fred); - - CFX_ByteString empty; - EXPECT_EQ(0u, empty.Delete(0)); - EXPECT_EQ("", empty); - EXPECT_EQ(0u, empty.Delete(1)); - EXPECT_EQ("", empty); -} - -TEST(fxcrt, ByteStringMid) { - CFX_ByteString fred("FRED"); - EXPECT_EQ("", fred.Mid(0, 0)); - EXPECT_EQ("", fred.Mid(3, 0)); - EXPECT_EQ("FRED", fred.Mid(0, 4)); - EXPECT_EQ("RED", fred.Mid(1, 3)); - EXPECT_EQ("ED", fred.Mid(2, 2)); - EXPECT_EQ("D", fred.Mid(3, 1)); - EXPECT_EQ("F", fred.Mid(0, 1)); - EXPECT_EQ("R", fred.Mid(1, 1)); - EXPECT_EQ("E", fred.Mid(2, 1)); - EXPECT_EQ("D", fred.Mid(3, 1)); - EXPECT_EQ("FR", fred.Mid(0, 2)); - EXPECT_EQ("FRED", fred.Mid(0, 4)); - EXPECT_EQ("", fred.Mid(0, 10)); - - EXPECT_EQ("RED", fred.Mid(1, 3)); - EXPECT_EQ("", fred.Mid(4, 1)); - - CFX_ByteString empty; - EXPECT_EQ("", empty.Mid(0, 0)); -} - -TEST(fxcrt, ByteStringLeft) { - CFX_ByteString fred("FRED"); - EXPECT_EQ("", fred.Left(0)); - EXPECT_EQ("F", fred.Left(1)); - EXPECT_EQ("FR", fred.Left(2)); - EXPECT_EQ("FRE", fred.Left(3)); - EXPECT_EQ("FRED", fred.Left(4)); - - EXPECT_EQ("", fred.Left(5)); - - CFX_ByteString empty; - EXPECT_EQ("", empty.Left(0)); - EXPECT_EQ("", empty.Left(1)); -} - -TEST(fxcrt, ByteStringRight) { - CFX_ByteString fred("FRED"); - EXPECT_EQ("", fred.Right(0)); - EXPECT_EQ("D", fred.Right(1)); - EXPECT_EQ("ED", fred.Right(2)); - EXPECT_EQ("RED", fred.Right(3)); - EXPECT_EQ("FRED", fred.Right(4)); - - EXPECT_EQ("", fred.Right(5)); - - CFX_ByteString empty; - EXPECT_EQ("", empty.Right(0)); - EXPECT_EQ("", empty.Right(1)); -} - -TEST(fxcrt, ByteStringFind) { - CFX_ByteString null_string; - EXPECT_FALSE(null_string.Find('a').has_value()); - EXPECT_FALSE(null_string.Find('\0').has_value()); - - CFX_ByteString empty_string(""); - EXPECT_FALSE(empty_string.Find('a').has_value()); - EXPECT_FALSE(empty_string.Find('\0').has_value()); - - pdfium::Optional result; - CFX_ByteString single_string("a"); - result = single_string.Find('a'); - ASSERT_TRUE(result.has_value()); - EXPECT_EQ(0u, result.value()); - EXPECT_FALSE(single_string.Find('b').has_value()); - EXPECT_FALSE(single_string.Find('\0').has_value()); - - CFX_ByteString longer_string("abccc"); - result = longer_string.Find('a'); - ASSERT_TRUE(result.has_value()); - EXPECT_EQ(0u, result.value()); - result = longer_string.Find('c'); - ASSERT_TRUE(result.has_value()); - EXPECT_EQ(2u, result.value()); - result = longer_string.Find('c', 3); - ASSERT_TRUE(result.has_value()); - EXPECT_EQ(3u, result.value()); - EXPECT_FALSE(longer_string.Find('d').has_value()); - EXPECT_FALSE(longer_string.Find('\0').has_value()); - - result = longer_string.Find("ab"); - ASSERT_TRUE(result.has_value()); - EXPECT_EQ(0u, result.value()); - result = longer_string.Find("ccc"); - ASSERT_TRUE(result.has_value()); - EXPECT_EQ(2u, result.value()); - result = longer_string.Find("cc", 3); - ASSERT_TRUE(result.has_value()); - EXPECT_EQ(3u, result.value()); - EXPECT_FALSE(longer_string.Find("d").has_value()); - - CFX_ByteString hibyte_string( - "ab\x8c" - "def"); - result = hibyte_string.Find('\x8c'); - ASSERT_TRUE(result.has_value()); - EXPECT_EQ(2u, result.value()); -} - -TEST(fxcrt, ByteStringReverseFind) { - CFX_ByteString null_string; - EXPECT_FALSE(null_string.ReverseFind('a').has_value()); - EXPECT_FALSE(null_string.ReverseFind('\0').has_value()); - - CFX_ByteString empty_string(""); - EXPECT_FALSE(empty_string.ReverseFind('a').has_value()); - EXPECT_FALSE(empty_string.ReverseFind('\0').has_value()); - - pdfium::Optional result; - CFX_ByteString single_string("a"); - result = single_string.ReverseFind('a'); - ASSERT_TRUE(result.has_value()); - EXPECT_EQ(0u, result.value()); - EXPECT_FALSE(single_string.ReverseFind('b').has_value()); - EXPECT_FALSE(single_string.ReverseFind('\0').has_value()); - - CFX_ByteString longer_string("abccc"); - result = longer_string.ReverseFind('a'); - ASSERT_TRUE(result.has_value()); - EXPECT_EQ(0u, result.value()); - result = longer_string.ReverseFind('c'); - ASSERT_TRUE(result.has_value()); - EXPECT_EQ(4u, result.value()); - EXPECT_FALSE(longer_string.ReverseFind('\0').has_value()); - - CFX_ByteString hibyte_string( - "ab\x8c" - "def"); - result = hibyte_string.ReverseFind('\x8c'); - ASSERT_TRUE(result.has_value()); - EXPECT_EQ(2u, result.value()); -} - -TEST(fxcrt, ByteStringUpperLower) { - CFX_ByteString fred("F-Re.42D"); - fred.MakeLower(); - EXPECT_EQ("f-re.42d", fred); - fred.MakeUpper(); - EXPECT_EQ("F-RE.42D", fred); - - CFX_ByteString empty; - empty.MakeLower(); - EXPECT_EQ("", empty); - empty.MakeUpper(); - EXPECT_EQ("", empty); -} - -TEST(fxcrt, ByteStringTrimRight) { - CFX_ByteString fred(" FRED "); - fred.TrimRight(); - EXPECT_EQ(" FRED", fred); - fred.TrimRight('E'); - EXPECT_EQ(" FRED", fred); - fred.TrimRight('D'); - EXPECT_EQ(" FRE", fred); - fred.TrimRight("ERP"); - EXPECT_EQ(" F", fred); - - CFX_ByteString blank(" "); - blank.TrimRight("ERP"); - EXPECT_EQ(" ", blank); - blank.TrimRight('E'); - EXPECT_EQ(" ", blank); - blank.TrimRight(); - EXPECT_EQ("", blank); - - CFX_ByteString empty; - empty.TrimRight("ERP"); - EXPECT_EQ("", empty); - empty.TrimRight('E'); - EXPECT_EQ("", empty); - empty.TrimRight(); - EXPECT_EQ("", empty); -} - -TEST(fxcrt, ByteStringTrimRightCopies) { - { - // With a single reference, no copy takes place. - CFX_ByteString fred(" FRED "); - const char* old_buffer = fred.c_str(); - fred.TrimRight(); - EXPECT_EQ(" FRED", fred); - EXPECT_EQ(old_buffer, fred.c_str()); - } - { - // With multiple references, we must copy. - CFX_ByteString fred(" FRED "); - CFX_ByteString other_fred = fred; - const char* old_buffer = fred.c_str(); - fred.TrimRight(); - EXPECT_EQ(" FRED", fred); - EXPECT_EQ(" FRED ", other_fred); - EXPECT_NE(old_buffer, fred.c_str()); - } - { - // With multiple references, but no modifications, no copy. - CFX_ByteString fred("FRED"); - CFX_ByteString other_fred = fred; - const char* old_buffer = fred.c_str(); - fred.TrimRight(); - EXPECT_EQ("FRED", fred); - EXPECT_EQ("FRED", other_fred); - EXPECT_EQ(old_buffer, fred.c_str()); - } -} - -TEST(fxcrt, ByteStringTrimLeft) { - CFX_ByteString fred(" FRED "); - fred.TrimLeft(); - EXPECT_EQ("FRED ", fred); - fred.TrimLeft('E'); - EXPECT_EQ("FRED ", fred); - fred.TrimLeft('F'); - EXPECT_EQ("RED ", fred); - fred.TrimLeft("ERP"); - EXPECT_EQ("D ", fred); - - CFX_ByteString blank(" "); - blank.TrimLeft("ERP"); - EXPECT_EQ(" ", blank); - blank.TrimLeft('E'); - EXPECT_EQ(" ", blank); - blank.TrimLeft(); - EXPECT_EQ("", blank); - - CFX_ByteString empty; - empty.TrimLeft("ERP"); - EXPECT_EQ("", empty); - empty.TrimLeft('E'); - EXPECT_EQ("", empty); - empty.TrimLeft(); - EXPECT_EQ("", empty); -} - -TEST(fxcrt, ByteStringTrimLeftCopies) { - { - // With a single reference, no copy takes place. - CFX_ByteString fred(" FRED "); - const char* old_buffer = fred.c_str(); - fred.TrimLeft(); - EXPECT_EQ("FRED ", fred); - EXPECT_EQ(old_buffer, fred.c_str()); - } - { - // With multiple references, we must copy. - CFX_ByteString fred(" FRED "); - CFX_ByteString other_fred = fred; - const char* old_buffer = fred.c_str(); - fred.TrimLeft(); - EXPECT_EQ("FRED ", fred); - EXPECT_EQ(" FRED ", other_fred); - EXPECT_NE(old_buffer, fred.c_str()); - } - { - // With multiple references, but no modifications, no copy. - CFX_ByteString fred("FRED"); - CFX_ByteString other_fred = fred; - const char* old_buffer = fred.c_str(); - fred.TrimLeft(); - EXPECT_EQ("FRED", fred); - EXPECT_EQ("FRED", other_fred); - EXPECT_EQ(old_buffer, fred.c_str()); - } -} - -TEST(fxcrt, ByteStringReserve) { - { - CFX_ByteString str; - str.Reserve(6); - const char* old_buffer = str.c_str(); - str += "ABCDEF"; - EXPECT_EQ(old_buffer, str.c_str()); - str += "Blah Blah Blah Blah Blah Blah"; - EXPECT_NE(old_buffer, str.c_str()); - } - { - CFX_ByteString str("A"); - str.Reserve(6); - const char* old_buffer = str.c_str(); - str += "BCDEF"; - EXPECT_EQ(old_buffer, str.c_str()); - str += "Blah Blah Blah Blah Blah Blah"; - EXPECT_NE(old_buffer, str.c_str()); - } -} - -TEST(fxcrt, ByteStringGetBuffer) { - { - CFX_ByteString str; - char* buffer = str.GetBuffer(12); - // NOLINTNEXTLINE(runtime/printf) - strcpy(buffer, "clams"); - str.ReleaseBuffer(str.GetStringLength()); - EXPECT_EQ("clams", str); - } - { - CFX_ByteString str("cl"); - char* buffer = str.GetBuffer(12); - // NOLINTNEXTLINE(runtime/printf) - strcpy(buffer + 2, "ams"); - str.ReleaseBuffer(str.GetStringLength()); - EXPECT_EQ("clams", str); - } -} - -TEST(fxcrt, ByteStringReleaseBuffer) { - { - CFX_ByteString str; - str.Reserve(12); - str += "clams"; - const char* old_buffer = str.c_str(); - str.ReleaseBuffer(4); - EXPECT_EQ(old_buffer, str.c_str()); - EXPECT_EQ("clam", str); - } - { - CFX_ByteString str("c"); - str.Reserve(12); - str += "lams"; - const char* old_buffer = str.c_str(); - str.ReleaseBuffer(4); - EXPECT_EQ(old_buffer, str.c_str()); - EXPECT_EQ("clam", str); - } - { - CFX_ByteString str; - str.Reserve(200); - str += "clams"; - const char* old_buffer = str.c_str(); - str.ReleaseBuffer(4); - EXPECT_NE(old_buffer, str.c_str()); - EXPECT_EQ("clam", str); - } - { - CFX_ByteString str("c"); - str.Reserve(200); - str += "lams"; - const char* old_buffer = str.c_str(); - str.ReleaseBuffer(4); - EXPECT_NE(old_buffer, str.c_str()); - EXPECT_EQ("clam", str); - } -} - -TEST(fxcrt, ByteStringEmptyReverseIterator) { - CFX_ByteString empty; - auto iter = empty.rbegin(); - EXPECT_TRUE(iter == empty.rend()); - EXPECT_FALSE(iter != empty.rend()); - EXPECT_FALSE(iter < empty.rend()); -} - -TEST(fxcrt, ByteStringOneCharReverseIterator) { - CFX_ByteString one_str("a"); - auto iter = one_str.rbegin(); - EXPECT_FALSE(iter == one_str.rend()); - EXPECT_TRUE(iter != one_str.rend()); - EXPECT_TRUE(iter < one_str.rend()); - - char ch = *iter++; - EXPECT_EQ('a', ch); - EXPECT_TRUE(iter == one_str.rend()); - EXPECT_FALSE(iter != one_str.rend()); - EXPECT_FALSE(iter < one_str.rend()); -} - -TEST(fxcrt, ByteStringMultiCharReverseIterator) { - CFX_ByteString multi_str("abcd"); - auto iter = multi_str.rbegin(); - EXPECT_FALSE(iter == multi_str.rend()); - - char ch = *iter++; - EXPECT_EQ('d', ch); - EXPECT_EQ('c', *iter); - EXPECT_FALSE(iter == multi_str.rend()); - - ch = *(++iter); - EXPECT_EQ('b', ch); - EXPECT_EQ('b', *iter); - EXPECT_FALSE(iter == multi_str.rend()); - - ch = *iter++; - EXPECT_EQ('b', ch); - EXPECT_EQ('a', *iter); - EXPECT_FALSE(iter == multi_str.rend()); - - ch = *iter++; - EXPECT_EQ('a', ch); - EXPECT_TRUE(iter == multi_str.rend()); - - ch = *(--iter); - EXPECT_EQ('a', ch); - EXPECT_EQ('a', *iter); - EXPECT_FALSE(iter == multi_str.rend()); - - ch = *iter--; - EXPECT_EQ('a', ch); - EXPECT_EQ('b', *iter); - EXPECT_FALSE(iter == multi_str.rend()); - - ch = *iter--; - EXPECT_EQ('b', ch); - EXPECT_EQ('c', *iter); - EXPECT_FALSE(iter == multi_str.rend()); - - ch = *(--iter); - EXPECT_EQ('d', ch); - EXPECT_EQ('d', *iter); - EXPECT_TRUE(iter == multi_str.rbegin()); -} - -TEST(fxcrt, ByteStringCNotNull) { - CFX_ByteStringC string3("abc"); - CFX_ByteStringC string6("abcdef"); - CFX_ByteStringC alternate_string3("abcdef", 3); - CFX_ByteStringC embedded_nul_string7("abc\0def", 7); - CFX_ByteStringC illegal_string7("abcdef", 7); - - EXPECT_EQ(3u, string3.GetLength()); - EXPECT_EQ(6u, string6.GetLength()); - EXPECT_EQ(3u, alternate_string3.GetLength()); - EXPECT_EQ(7u, embedded_nul_string7.GetLength()); - EXPECT_EQ(7u, illegal_string7.GetLength()); - - EXPECT_NE(string3, string6); - EXPECT_EQ(string3, alternate_string3); - EXPECT_NE(string3, embedded_nul_string7); - EXPECT_NE(string3, illegal_string7); - EXPECT_NE(string6, alternate_string3); - EXPECT_NE(string6, embedded_nul_string7); - EXPECT_NE(string6, illegal_string7); - EXPECT_NE(alternate_string3, embedded_nul_string7); - EXPECT_NE(alternate_string3, illegal_string7); - EXPECT_NE(embedded_nul_string7, illegal_string7); - - CFX_ByteStringC copied_string3(string3); - CFX_ByteStringC copied_alternate_string3(alternate_string3); - CFX_ByteStringC copied_embedded_nul_string7(embedded_nul_string7); - - EXPECT_EQ(string3, copied_string3); - EXPECT_EQ(alternate_string3, copied_alternate_string3); - EXPECT_EQ(embedded_nul_string7, copied_embedded_nul_string7); - - CFX_ByteStringC assigned_string3("intially something else"); - CFX_ByteStringC assigned_alternate_string3("initally something else"); - CFX_ByteStringC assigned_ptr_string3("initially something else"); - CFX_ByteStringC assigned_embedded_nul_string7("initially something else"); - - assigned_string3 = string3; - assigned_alternate_string3 = alternate_string3; - assigned_ptr_string3 = "abc"; - assigned_embedded_nul_string7 = embedded_nul_string7; - EXPECT_EQ(string3, assigned_string3); - EXPECT_EQ(alternate_string3, assigned_alternate_string3); - EXPECT_EQ(alternate_string3, assigned_ptr_string3); - EXPECT_EQ(embedded_nul_string7, assigned_embedded_nul_string7); -} - -TEST(fxcrt, ByteStringCFromChar) { - CFX_ByteStringC null_string; - CFX_ByteStringC lower_a_string("a"); - - // Must have lvalues that outlive the corresponding ByteStringC. - char nul = '\0'; - char lower_a = 'a'; - CFX_ByteStringC nul_string_from_char(nul); - CFX_ByteStringC lower_a_string_from_char(lower_a); - - // Pointer to nul, not nullptr ptr, hence length 1 ... - EXPECT_EQ(1u, nul_string_from_char.GetLength()); - EXPECT_NE(null_string, nul_string_from_char); - - EXPECT_EQ(1u, lower_a_string_from_char.GetLength()); - EXPECT_EQ(lower_a_string, lower_a_string_from_char); - EXPECT_NE(nul_string_from_char, lower_a_string_from_char); - - CFX_ByteStringC longer_string("ab"); - EXPECT_NE(longer_string, lower_a_string_from_char); -} - -TEST(fxcrt, ByteStringCFromVector) { - std::vector null_vec; - CFX_ByteStringC null_string(null_vec); - EXPECT_EQ(0u, null_string.GetLength()); - - std::vector lower_a_vec(10, static_cast('a')); - CFX_ByteStringC lower_a_string(lower_a_vec); - EXPECT_EQ(static_cast(10), lower_a_string.GetLength()); - EXPECT_EQ("aaaaaaaaaa", lower_a_string); - - std::vector cleared_vec; - cleared_vec.push_back(42); - cleared_vec.pop_back(); - CFX_ByteStringC cleared_string(cleared_vec); - EXPECT_EQ(0u, cleared_string.GetLength()); - EXPECT_EQ(nullptr, cleared_string.raw_str()); -} - -TEST(fxcrt, ByteStringCGetID) { - CFX_ByteStringC null_string; - EXPECT_EQ(0u, null_string.GetID()); - - CFX_ByteStringC empty_string(""); - EXPECT_EQ(0u, empty_string.GetID()); - - CFX_ByteStringC short_string("ab"); - EXPECT_EQ(FXBSTR_ID('a', 'b', 0, 0), short_string.GetID()); - - CFX_ByteStringC longer_string("abcdef"); - EXPECT_EQ(FXBSTR_ID('a', 'b', 'c', 'd'), longer_string.GetID()); -} - -TEST(fxcrt, ByteStringCFind) { - CFX_ByteStringC null_string; - EXPECT_FALSE(null_string.Find('a').has_value()); - EXPECT_FALSE(null_string.Find('\0').has_value()); - - CFX_ByteStringC empty_string(""); - EXPECT_FALSE(empty_string.Find('a').has_value()); - EXPECT_FALSE(empty_string.Find('\0').has_value()); - - pdfium::Optional result; - CFX_ByteStringC single_string("a"); - result = single_string.Find('a'); - ASSERT_TRUE(result.has_value()); - EXPECT_EQ(0u, result.value()); - EXPECT_FALSE(single_string.Find('b').has_value()); - EXPECT_FALSE(single_string.Find('\0').has_value()); - - CFX_ByteStringC longer_string("abccc"); - result = longer_string.Find('a'); - ASSERT_TRUE(result.has_value()); - EXPECT_EQ(0u, result.value()); - result = longer_string.Find('c'); - ASSERT_TRUE(result.has_value()); - EXPECT_EQ(2u, result.value()); - EXPECT_FALSE(longer_string.Find('d').has_value()); - EXPECT_FALSE(longer_string.Find('\0').has_value()); - - CFX_ByteStringC hibyte_string( - "ab\x8c" - "def"); - result = hibyte_string.Find('\x8c'); - ASSERT_TRUE(result.has_value()); - EXPECT_EQ(2u, result.value()); -} - -TEST(fxcrt, ByteStringCMid) { - CFX_ByteStringC null_string; - EXPECT_EQ(null_string, null_string.Mid(0, 1)); - EXPECT_EQ(null_string, null_string.Mid(1, 1)); - - CFX_ByteStringC empty_string(""); - EXPECT_EQ("", empty_string.Mid(0, 1)); - EXPECT_EQ("", empty_string.Mid(1, 1)); - - CFX_ByteStringC single_character("a"); - EXPECT_EQ("", single_character.Mid(0, 0)); - EXPECT_EQ(single_character, single_character.Mid(0, 1)); - EXPECT_EQ("", single_character.Mid(1, 0)); - EXPECT_EQ("", single_character.Mid(1, 1)); - - CFX_ByteStringC longer_string("abcdef"); - EXPECT_EQ(longer_string, longer_string.Mid(0, 6)); - EXPECT_EQ("", longer_string.Mid(0, 187)); - - CFX_ByteStringC leading_substring("ab"); - EXPECT_EQ(leading_substring, longer_string.Mid(0, 2)); - - CFX_ByteStringC middle_substring("bcde"); - EXPECT_EQ(middle_substring, longer_string.Mid(1, 4)); - - CFX_ByteStringC trailing_substring("ef"); - EXPECT_EQ(trailing_substring, longer_string.Mid(4, 2)); - EXPECT_EQ("", longer_string.Mid(4, 3)); -} - -TEST(fxcrt, ByteStringCTrimmedRight) { - CFX_ByteStringC fred("FRED"); - EXPECT_EQ("FRED", fred.TrimmedRight('E')); - EXPECT_EQ("FRE", fred.TrimmedRight('D')); - CFX_ByteStringC fredd("FREDD"); - EXPECT_EQ("FRE", fred.TrimmedRight('D')); -} - -TEST(fxcrt, ByteStringCElementAccess) { - // CFX_ByteStringC includes the NUL terminator for non-empty strings. - CFX_ByteStringC abc("abc"); - EXPECT_EQ('a', static_cast(abc[0])); - EXPECT_EQ('b', static_cast(abc[1])); - EXPECT_EQ('c', static_cast(abc[2])); -#ifndef NDEBUG - EXPECT_DEATH({ abc[3]; }, ".*"); -#endif -} - -TEST(fxcrt, ByteStringCOperatorLT) { - CFX_ByteStringC empty; - CFX_ByteStringC a("a"); - CFX_ByteStringC abc("abc"); - CFX_ByteStringC def("def"); - - EXPECT_FALSE(empty < empty); - EXPECT_FALSE(a < a); - EXPECT_FALSE(abc < abc); - EXPECT_FALSE(def < def); - - EXPECT_TRUE(empty < a); - EXPECT_FALSE(a < empty); - - EXPECT_TRUE(empty < abc); - EXPECT_FALSE(abc < empty); - - EXPECT_TRUE(empty < def); - EXPECT_FALSE(def < empty); - - EXPECT_TRUE(a < abc); - EXPECT_FALSE(abc < a); - - EXPECT_TRUE(a < def); - EXPECT_FALSE(def < a); - - EXPECT_TRUE(abc < def); - EXPECT_FALSE(def < abc); -} - -TEST(fxcrt, ByteStringCOperatorEQ) { - CFX_ByteStringC byte_string_c("hello"); - EXPECT_TRUE(byte_string_c == byte_string_c); - - CFX_ByteStringC byte_string_c_same1("hello"); - EXPECT_TRUE(byte_string_c == byte_string_c_same1); - EXPECT_TRUE(byte_string_c_same1 == byte_string_c); - - CFX_ByteStringC byte_string_c_same2(byte_string_c); - EXPECT_TRUE(byte_string_c == byte_string_c_same2); - EXPECT_TRUE(byte_string_c_same2 == byte_string_c); - - CFX_ByteStringC byte_string_c1("he"); - CFX_ByteStringC byte_string_c2("hellp"); - CFX_ByteStringC byte_string_c3("hellod"); - EXPECT_FALSE(byte_string_c == byte_string_c1); - EXPECT_FALSE(byte_string_c == byte_string_c2); - EXPECT_FALSE(byte_string_c == byte_string_c3); - EXPECT_FALSE(byte_string_c1 == byte_string_c); - EXPECT_FALSE(byte_string_c2 == byte_string_c); - EXPECT_FALSE(byte_string_c3 == byte_string_c); - - CFX_ByteString byte_string_same1("hello"); - EXPECT_TRUE(byte_string_c == byte_string_same1); - EXPECT_TRUE(byte_string_same1 == byte_string_c); - - CFX_ByteString byte_string1("he"); - CFX_ByteString byte_string2("hellp"); - CFX_ByteString byte_string3("hellod"); - EXPECT_FALSE(byte_string_c == byte_string1); - EXPECT_FALSE(byte_string_c == byte_string2); - EXPECT_FALSE(byte_string_c == byte_string3); - EXPECT_FALSE(byte_string1 == byte_string_c); - EXPECT_FALSE(byte_string2 == byte_string_c); - EXPECT_FALSE(byte_string3 == byte_string_c); - - const char* c_string_same1 = "hello"; - EXPECT_TRUE(byte_string_c == c_string_same1); - EXPECT_TRUE(c_string_same1 == byte_string_c); - - const char* c_string1 = "he"; - const char* c_string2 = "hellp"; - const char* c_string3 = "hellod"; - EXPECT_FALSE(byte_string_c == c_string1); - EXPECT_FALSE(byte_string_c == c_string2); - EXPECT_FALSE(byte_string_c == c_string3); - - EXPECT_FALSE(c_string1 == byte_string_c); - EXPECT_FALSE(c_string2 == byte_string_c); - EXPECT_FALSE(c_string3 == byte_string_c); -} - -TEST(fxcrt, ByteStringCOperatorNE) { - CFX_ByteStringC byte_string_c("hello"); - EXPECT_FALSE(byte_string_c != byte_string_c); - - CFX_ByteStringC byte_string_c_same1("hello"); - EXPECT_FALSE(byte_string_c != byte_string_c_same1); - EXPECT_FALSE(byte_string_c_same1 != byte_string_c); - - CFX_ByteStringC byte_string_c_same2(byte_string_c); - EXPECT_FALSE(byte_string_c != byte_string_c_same2); - EXPECT_FALSE(byte_string_c_same2 != byte_string_c); - - CFX_ByteStringC byte_string_c1("he"); - CFX_ByteStringC byte_string_c2("hellp"); - CFX_ByteStringC byte_string_c3("hellod"); - EXPECT_TRUE(byte_string_c != byte_string_c1); - EXPECT_TRUE(byte_string_c != byte_string_c2); - EXPECT_TRUE(byte_string_c != byte_string_c3); - EXPECT_TRUE(byte_string_c1 != byte_string_c); - EXPECT_TRUE(byte_string_c2 != byte_string_c); - EXPECT_TRUE(byte_string_c3 != byte_string_c); - - CFX_ByteString byte_string_same1("hello"); - EXPECT_FALSE(byte_string_c != byte_string_same1); - EXPECT_FALSE(byte_string_same1 != byte_string_c); - - CFX_ByteString byte_string1("he"); - CFX_ByteString byte_string2("hellp"); - CFX_ByteString byte_string3("hellod"); - EXPECT_TRUE(byte_string_c != byte_string1); - EXPECT_TRUE(byte_string_c != byte_string2); - EXPECT_TRUE(byte_string_c != byte_string3); - EXPECT_TRUE(byte_string1 != byte_string_c); - EXPECT_TRUE(byte_string2 != byte_string_c); - EXPECT_TRUE(byte_string3 != byte_string_c); - - const char* c_string_same1 = "hello"; - EXPECT_FALSE(byte_string_c != c_string_same1); - EXPECT_FALSE(c_string_same1 != byte_string_c); - - const char* c_string1 = "he"; - const char* c_string2 = "hellp"; - const char* c_string3 = "hellod"; - EXPECT_TRUE(byte_string_c != c_string1); - EXPECT_TRUE(byte_string_c != c_string2); - EXPECT_TRUE(byte_string_c != c_string3); - - EXPECT_TRUE(c_string1 != byte_string_c); - EXPECT_TRUE(c_string2 != byte_string_c); - EXPECT_TRUE(c_string3 != byte_string_c); -} - -TEST(fxcrt, ByteStringCNullIterator) { - CFX_ByteStringC null_str; - int32_t sum = 0; - bool any_present = false; - for (const auto& c : null_str) { - sum += c; // Avoid unused arg warnings. - any_present = true; - } - EXPECT_FALSE(any_present); - EXPECT_EQ(0, sum); -} - -TEST(fxcrt, ByteStringCEmptyIterator) { - CFX_ByteStringC empty_str(""); - int32_t sum = 0; - bool any_present = false; - for (const auto& c : empty_str) { - any_present = true; - sum += c; // Avoid unused arg warnings. - } - EXPECT_FALSE(any_present); - EXPECT_EQ(0, sum); -} - -TEST(fxcrt, ByteStringCOneCharIterator) { - CFX_ByteStringC one_str("a"); - int32_t sum = 0; - bool any_present = false; - for (const auto& c : one_str) { - any_present = true; - sum += c; // Avoid unused arg warnings. - } - EXPECT_TRUE(any_present); - EXPECT_EQ('a', sum); -} - -TEST(fxcrt, ByteStringCMultiCharIterator) { - CFX_ByteStringC one_str("abc"); - int32_t sum = 0; - bool any_present = false; - for (const auto& c : one_str) { - any_present = true; - sum += c; // Avoid unused arg warnings. - } - EXPECT_TRUE(any_present); - EXPECT_EQ('a' + 'b' + 'c', sum); -} - -TEST(fxcrt, ByteStringCEmptyReverseIterator) { - CFX_ByteStringC empty; - auto iter = empty.rbegin(); - EXPECT_TRUE(iter == empty.rend()); - EXPECT_FALSE(iter != empty.rend()); - EXPECT_FALSE(iter < empty.rend()); -} - -TEST(fxcrt, ByteStringCOneCharReverseIterator) { - CFX_ByteStringC one_str("a"); - auto iter = one_str.rbegin(); - EXPECT_FALSE(iter == one_str.rend()); - EXPECT_TRUE(iter != one_str.rend()); - EXPECT_TRUE(iter < one_str.rend()); - - char ch = *iter++; - EXPECT_EQ('a', ch); - EXPECT_TRUE(iter == one_str.rend()); - EXPECT_FALSE(iter != one_str.rend()); - EXPECT_FALSE(iter < one_str.rend()); -} - -TEST(fxcrt, ByteStringCMultiCharReverseIterator) { - CFX_ByteStringC multi_str("abcd"); - auto iter = multi_str.rbegin(); - EXPECT_FALSE(iter == multi_str.rend()); - - char ch = *iter++; - EXPECT_EQ('d', ch); - EXPECT_EQ('c', *iter); - EXPECT_FALSE(iter == multi_str.rend()); - - ch = *(++iter); - EXPECT_EQ('b', ch); - EXPECT_EQ('b', *iter); - EXPECT_FALSE(iter == multi_str.rend()); - - ch = *iter++; - EXPECT_EQ('b', ch); - EXPECT_EQ('a', *iter); - EXPECT_FALSE(iter == multi_str.rend()); - - ch = *iter++; - EXPECT_EQ('a', ch); - EXPECT_TRUE(iter == multi_str.rend()); - - ch = *(--iter); - EXPECT_EQ('a', ch); - EXPECT_EQ('a', *iter); - EXPECT_FALSE(iter == multi_str.rend()); - - ch = *iter--; - EXPECT_EQ('a', ch); - EXPECT_EQ('b', *iter); - EXPECT_FALSE(iter == multi_str.rend()); - - ch = *iter--; - EXPECT_EQ('b', ch); - EXPECT_EQ('c', *iter); - EXPECT_FALSE(iter == multi_str.rend()); - - ch = *(--iter); - EXPECT_EQ('d', ch); - EXPECT_EQ('d', *iter); - EXPECT_TRUE(iter == multi_str.rbegin()); -} - -TEST(fxcrt, ByteStringCAnyAllNoneOf) { - CFX_ByteStringC str("aaaaaaaaaaaaaaaaab"); - EXPECT_FALSE(std::all_of(str.begin(), str.end(), - [](const char& c) { return c == 'a'; })); - - EXPECT_FALSE(std::none_of(str.begin(), str.end(), - [](const char& c) { return c == 'a'; })); - - EXPECT_TRUE(std::any_of(str.begin(), str.end(), - [](const char& c) { return c == 'a'; })); - - EXPECT_TRUE(pdfium::ContainsValue(str, 'a')); - EXPECT_TRUE(pdfium::ContainsValue(str, 'b')); - EXPECT_FALSE(pdfium::ContainsValue(str, 'z')); -} - -TEST(fxcrt, ByteStringFormatWidth) { - { - CFX_ByteString str; - str.Format("%5d", 1); - EXPECT_EQ(" 1", str); - } - - { - CFX_ByteString str; - str.Format("%d", 1); - EXPECT_EQ("1", str); - } - - { - CFX_ByteString str; - str.Format("%*d", 5, 1); - EXPECT_EQ(" 1", str); - } - - { - CFX_ByteString str; - str.Format("%-1d", 1); - EXPECT_EQ("1", str); - } - - { - CFX_ByteString str; - str.Format("%0d", 1); - EXPECT_EQ("1", str); - } -} - -TEST(fxcrt, ByteStringFormatPrecision) { - { - CFX_ByteString str; - str.Format("%.2f", 1.12345); - EXPECT_EQ("1.12", str); - } - - { - CFX_ByteString str; - str.Format("%.*f", 3, 1.12345); - EXPECT_EQ("1.123", str); - } - - { - CFX_ByteString str; - str.Format("%f", 1.12345); - EXPECT_EQ("1.123450", str); - } - - { - CFX_ByteString str; - str.Format("%-1f", 1.12345); - EXPECT_EQ("1.123450", str); - } - - { - CFX_ByteString str; - str.Format("%0f", 1.12345); - EXPECT_EQ("1.123450", str); - } -} - -TEST(fxcrt, EmptyByteString) { - CFX_ByteString empty_str; - EXPECT_TRUE(empty_str.IsEmpty()); - EXPECT_EQ(0u, empty_str.GetLength()); - const char* cstr = empty_str.c_str(); - EXPECT_EQ(0u, FXSYS_strlen(cstr)); -} - -TEST(fxcrt, ByteStringInitializerList) { - CFX_ByteString many_str({"clams", " and ", "oysters"}); - EXPECT_EQ("clams and oysters", many_str); - many_str = {"fish", " and ", "chips", " and ", "soda"}; - EXPECT_EQ("fish and chips and soda", many_str); -} - -TEST(fxcrt, ByteStringNullIterator) { - CFX_ByteString null_str; - int32_t sum = 0; - bool any_present = false; - for (const auto& c : null_str) { - sum += c; // Avoid unused arg warnings. - any_present = true; - } - EXPECT_FALSE(any_present); - EXPECT_EQ(0, sum); -} - -TEST(fxcrt, ByteStringEmptyIterator) { - CFX_ByteString empty_str(""); - int32_t sum = 0; - bool any_present = false; - for (const auto& c : empty_str) { - any_present = true; - sum += c; // Avoid unused arg warnings. - } - EXPECT_FALSE(any_present); - EXPECT_EQ(0, sum); -} - -TEST(fxcrt, ByteStringOneCharIterator) { - CFX_ByteString one_str("a"); - int32_t sum = 0; - bool any_present = false; - for (const auto& c : one_str) { - any_present = true; - sum += c; // Avoid unused arg warnings. - } - EXPECT_TRUE(any_present); - EXPECT_EQ('a', sum); -} - -TEST(fxcrt, ByteStringMultiCharIterator) { - CFX_ByteString one_str("abc"); - int32_t sum = 0; - bool any_present = false; - for (const auto& c : one_str) { - any_present = true; - sum += c; // Avoid unused arg warnings. - } - EXPECT_TRUE(any_present); - EXPECT_EQ('a' + 'b' + 'c', sum); -} - -TEST(fxcrt, ByteStringAnyAllNoneOf) { - CFX_ByteString str("aaaaaaaaaaaaaaaaab"); - EXPECT_FALSE(std::all_of(str.begin(), str.end(), - [](const char& c) { return c == 'a'; })); - - EXPECT_FALSE(std::none_of(str.begin(), str.end(), - [](const char& c) { return c == 'a'; })); - - EXPECT_TRUE(std::any_of(str.begin(), str.end(), - [](const char& c) { return c == 'a'; })); - - EXPECT_TRUE(pdfium::ContainsValue(str, 'a')); - EXPECT_TRUE(pdfium::ContainsValue(str, 'b')); - EXPECT_FALSE(pdfium::ContainsValue(str, 'z')); -} - -TEST(fxcrt, EqualNoCase) { - CFX_ByteString str("aaa"); - EXPECT_TRUE(str.EqualNoCase("aaa")); - EXPECT_TRUE(str.EqualNoCase("AAA")); - EXPECT_TRUE(str.EqualNoCase("aaA")); - EXPECT_TRUE(str.EqualNoCase("Aaa")); - EXPECT_FALSE(str.EqualNoCase("aab")); - EXPECT_FALSE(str.EqualNoCase("aaaa")); - EXPECT_FALSE(str.EqualNoCase("BBBB")); - EXPECT_FALSE(str.EqualNoCase("a")); - EXPECT_FALSE(str.EqualNoCase("")); -} - -TEST(fxcrt, OStreamByteStringOverload) { - std::ostringstream stream; - - // Basic case, empty string - CFX_ByteString str; - stream << str; - EXPECT_EQ("", stream.str()); - - // Basic case, non-empty string - str = "def"; - stream.str(""); - stream << "abc" << str << "ghi"; - EXPECT_EQ("abcdefghi", stream.str()); - - // Changing the CFX_ByteString does not change the stream it was written to. - str = "123"; - EXPECT_EQ("abcdefghi", stream.str()); - - // Writing it again to the stream will use the latest value. - stream.str(""); - stream << "abc" << str << "ghi"; - EXPECT_EQ("abc123ghi", stream.str()); - - char stringWithNulls[]{'x', 'y', '\0', 'z'}; - - // Writing a CFX_ByteString with nulls and no specified length treats it as - // a C-style null-terminated string. - str = CFX_ByteString(stringWithNulls); - EXPECT_EQ(2u, str.GetLength()); - stream.str(""); - stream << str; - EXPECT_EQ(2u, stream.tellp()); - - // Writing a CFX_ByteString with nulls but specifying its length treats it as - // a C++-style string. - str = CFX_ByteString(stringWithNulls, 4); - EXPECT_EQ(4u, str.GetLength()); - stream.str(""); - stream << str; - EXPECT_EQ(4u, stream.tellp()); - - // << operators can be chained. - CFX_ByteString str1("abc"); - CFX_ByteString str2("def"); - stream.str(""); - stream << str1 << str2; - EXPECT_EQ("abcdef", stream.str()); -} - -TEST(fxcrt, OStreamByteStringCOverload) { - // Basic case, empty string - { - std::ostringstream stream; - CFX_ByteStringC str; - stream << str; - EXPECT_EQ("", stream.str()); - } - - // Basic case, non-empty string - { - std::ostringstream stream; - CFX_ByteStringC str("def"); - stream << "abc" << str << "ghi"; - EXPECT_EQ("abcdefghi", stream.str()); - } - - // Changing the CFX_ByteStringC does not change the stream it was written to. - { - std::ostringstream stream; - CFX_ByteStringC str("abc"); - stream << str; - str = "123"; - EXPECT_EQ("abc", stream.str()); - } - - // Writing it again to the stream will use the latest value. - { - std::ostringstream stream; - CFX_ByteStringC str("abc"); - stream << str; - stream.str(""); - str = "123"; - stream << str; - EXPECT_EQ("123", stream.str()); - } - - // Writing a CFX_ByteStringC with nulls and no specified length treats it as - // a C-style null-terminated string. - { - std::ostringstream stream; - char stringWithNulls[]{'x', 'y', '\0', 'z'}; - CFX_ByteStringC str(stringWithNulls); - EXPECT_EQ(2u, str.GetLength()); - stream << str; - EXPECT_EQ(2u, stream.tellp()); - str = ""; - } - - // Writing a CFX_ByteStringC with nulls but specifying its length treats it as - // a C++-style string. - { - std::ostringstream stream; - char stringWithNulls[]{'x', 'y', '\0', 'z'}; - CFX_ByteStringC str(stringWithNulls, 4); - EXPECT_EQ(4u, str.GetLength()); - stream << str; - EXPECT_EQ(4u, stream.tellp()); - str = ""; - } - - // << operators can be chained. - { - std::ostringstream stream; - CFX_ByteStringC str1("abc"); - CFX_ByteStringC str2("def"); - stream << str1 << str2; - EXPECT_EQ("abcdef", stream.str()); - } -} - -TEST(fxcrt, ByteStringFormatInteger) { - // Base case of 0. - EXPECT_EQ("0", CFX_ByteString::FormatInteger(0)); - - // Positive ordinary number. - EXPECT_EQ("123456", CFX_ByteString::FormatInteger(123456)); - - // Negative ordinary number. - EXPECT_EQ("-123456", CFX_ByteString::FormatInteger(-123456)); - - // int limits. - EXPECT_EQ("2147483647", CFX_ByteString::FormatInteger(INT_MAX)); - EXPECT_EQ("-2147483648", CFX_ByteString::FormatInteger(INT_MIN)); -} diff --git a/core/fxcrt/cfx_checksumcontext.cpp b/core/fxcrt/cfx_checksumcontext.cpp index 31140169b4..c75e440231 100644 --- a/core/fxcrt/cfx_checksumcontext.cpp +++ b/core/fxcrt/cfx_checksumcontext.cpp @@ -140,11 +140,11 @@ void CFX_ChecksumContext::FinishChecksum() { } } -CFX_ByteString CFX_ChecksumContext::GetChecksum() const { +ByteString CFX_ChecksumContext::GetChecksum() const { return m_bsChecksum; } -void CFX_ChecksumContext::Update(const CFX_ByteStringC& bsText) { +void CFX_ChecksumContext::Update(const ByteStringView& bsText) { if (!m_pByteContext) return; diff --git a/core/fxcrt/cfx_checksumcontext.h b/core/fxcrt/cfx_checksumcontext.h index 8869c540fb..4231e09a83 100644 --- a/core/fxcrt/cfx_checksumcontext.h +++ b/core/fxcrt/cfx_checksumcontext.h @@ -18,17 +18,17 @@ class CFX_ChecksumContext { ~CFX_ChecksumContext(); void StartChecksum(); - void Update(const CFX_ByteStringC& bsText); + void Update(const ByteStringView& bsText); bool UpdateChecksum(const CFX_RetainPtr& pSrcFile, FX_FILESIZE offset = 0, size_t size = 0); void FinishChecksum(); - CFX_ByteString GetChecksum() const; + ByteString GetChecksum() const; private: std::unique_ptr m_pSAXReader; std::unique_ptr m_pByteContext; - CFX_ByteString m_bsChecksum; + ByteString m_bsChecksum; }; #endif // CORE_FXCRT_CFX_CHECKSUMCONTEXT_H_ diff --git a/core/fxcrt/cfx_crtfileaccess.cpp b/core/fxcrt/cfx_crtfileaccess.cpp index ddca68e144..2479c95654 100644 --- a/core/fxcrt/cfx_crtfileaccess.cpp +++ b/core/fxcrt/cfx_crtfileaccess.cpp @@ -6,7 +6,7 @@ #include "core/fxcrt/cfx_crtfileaccess.h" -CFX_CRTFileAccess::CFX_CRTFileAccess(const CFX_WideStringC& wsPath) +CFX_CRTFileAccess::CFX_CRTFileAccess(const WideStringView& wsPath) : m_path(wsPath) {} CFX_CRTFileAccess::~CFX_CRTFileAccess() {} diff --git a/core/fxcrt/cfx_crtfileaccess.h b/core/fxcrt/cfx_crtfileaccess.h index cb2a034f20..3c63aa30c3 100644 --- a/core/fxcrt/cfx_crtfileaccess.h +++ b/core/fxcrt/cfx_crtfileaccess.h @@ -19,10 +19,10 @@ class CFX_CRTFileAccess : public CFX_Retainable { CFX_RetainPtr CreateFileStream(uint32_t dwModes); private: - explicit CFX_CRTFileAccess(const CFX_WideStringC& wsPath); + explicit CFX_CRTFileAccess(const WideStringView& wsPath); ~CFX_CRTFileAccess() override; - CFX_WideString m_path; + WideString m_path; }; #endif // CORE_FXCRT_CFX_CRTFILEACCESS_H_ diff --git a/core/fxcrt/cfx_decimal.cpp b/core/fxcrt/cfx_decimal.cpp index b900e069a7..45980db6ee 100644 --- a/core/fxcrt/cfx_decimal.cpp +++ b/core/fxcrt/cfx_decimal.cpp @@ -294,7 +294,7 @@ CFX_Decimal::CFX_Decimal(float val, uint8_t scale) { m_uFlags = FXMATH_DECIMAL_MAKEFLAGS(val < 0 && IsNotZero(), scale); } -CFX_Decimal::CFX_Decimal(const CFX_WideStringC& strObj) { +CFX_Decimal::CFX_Decimal(const WideStringView& strObj) { const wchar_t* str = strObj.unterminated_c_str(); const wchar_t* strBound = str + strObj.GetLength(); bool pointmet = false; @@ -329,9 +329,9 @@ CFX_Decimal::CFX_Decimal(const CFX_WideStringC& strObj) { m_uFlags = FXMATH_DECIMAL_MAKEFLAGS(negmet && IsNotZero(), scale); } -CFX_Decimal::operator CFX_WideString() const { - CFX_WideString retString; - CFX_WideString tmpbuf; +CFX_Decimal::operator WideString() const { + WideString retString; + WideString tmpbuf; uint64_t phi = m_uHi; uint64_t pmid = m_uMid; uint64_t plo = m_uLo; diff --git a/core/fxcrt/cfx_decimal.h b/core/fxcrt/cfx_decimal.h index 544280444a..de6e3de5e5 100644 --- a/core/fxcrt/cfx_decimal.h +++ b/core/fxcrt/cfx_decimal.h @@ -16,9 +16,9 @@ class CFX_Decimal { explicit CFX_Decimal(uint64_t val); explicit CFX_Decimal(int32_t val); CFX_Decimal(float val, uint8_t scale); - explicit CFX_Decimal(const CFX_WideStringC& str); + explicit CFX_Decimal(const WideStringView& str); - operator CFX_WideString() const; + operator WideString() const; operator double() const; CFX_Decimal operator*(const CFX_Decimal& val) const; diff --git a/core/fxcrt/cfx_fileaccess_posix.cpp b/core/fxcrt/cfx_fileaccess_posix.cpp index 345b6641ef..d98e58dbe9 100644 --- a/core/fxcrt/cfx_fileaccess_posix.cpp +++ b/core/fxcrt/cfx_fileaccess_posix.cpp @@ -51,7 +51,7 @@ CFX_FileAccess_Posix::~CFX_FileAccess_Posix() { Close(); } -bool CFX_FileAccess_Posix::Open(const CFX_ByteStringC& fileName, +bool CFX_FileAccess_Posix::Open(const ByteStringView& fileName, uint32_t dwMode) { if (m_nFD > -1) return false; @@ -65,9 +65,9 @@ bool CFX_FileAccess_Posix::Open(const CFX_ByteStringC& fileName, return m_nFD > -1; } -bool CFX_FileAccess_Posix::Open(const CFX_WideStringC& fileName, +bool CFX_FileAccess_Posix::Open(const WideStringView& fileName, uint32_t dwMode) { - return Open(FX_UTF8Encode(fileName).AsStringC(), dwMode); + return Open(FX_UTF8Encode(fileName).AsStringView(), dwMode); } void CFX_FileAccess_Posix::Close() { diff --git a/core/fxcrt/cfx_fileaccess_posix.h b/core/fxcrt/cfx_fileaccess_posix.h index c299f6cc34..0b739e72d8 100644 --- a/core/fxcrt/cfx_fileaccess_posix.h +++ b/core/fxcrt/cfx_fileaccess_posix.h @@ -18,8 +18,8 @@ class CFX_FileAccess_Posix : public IFX_FileAccess { ~CFX_FileAccess_Posix() override; // IFX_FileAccess: - bool Open(const CFX_ByteStringC& fileName, uint32_t dwMode) override; - bool Open(const CFX_WideStringC& fileName, uint32_t dwMode) override; + bool Open(const ByteStringView& fileName, uint32_t dwMode) override; + bool Open(const WideStringView& fileName, uint32_t dwMode) override; void Close() override; FX_FILESIZE GetSize() const override; FX_FILESIZE GetPosition() const override; diff --git a/core/fxcrt/cfx_fileaccess_windows.cpp b/core/fxcrt/cfx_fileaccess_windows.cpp index b39a4d6efc..105ad788f7 100644 --- a/core/fxcrt/cfx_fileaccess_windows.cpp +++ b/core/fxcrt/cfx_fileaccess_windows.cpp @@ -54,7 +54,7 @@ CFX_FileAccess_Windows::~CFX_FileAccess_Windows() { Close(); } -bool CFX_FileAccess_Windows::Open(const CFX_ByteStringC& fileName, +bool CFX_FileAccess_Windows::Open(const ByteStringView& fileName, uint32_t dwMode) { if (m_hFile) return false; @@ -69,7 +69,7 @@ bool CFX_FileAccess_Windows::Open(const CFX_ByteStringC& fileName, return !!m_hFile; } -bool CFX_FileAccess_Windows::Open(const CFX_WideStringC& fileName, +bool CFX_FileAccess_Windows::Open(const WideStringView& fileName, uint32_t dwMode) { if (m_hFile) return false; diff --git a/core/fxcrt/cfx_fileaccess_windows.h b/core/fxcrt/cfx_fileaccess_windows.h index 692a537a82..f05ab39d6e 100644 --- a/core/fxcrt/cfx_fileaccess_windows.h +++ b/core/fxcrt/cfx_fileaccess_windows.h @@ -16,8 +16,8 @@ class CFX_FileAccess_Windows : public IFX_FileAccess { ~CFX_FileAccess_Windows() override; // IFX_FileAccess - bool Open(const CFX_ByteStringC& fileName, uint32_t dwMode) override; - bool Open(const CFX_WideStringC& fileName, uint32_t dwMode) override; + bool Open(const ByteStringView& fileName, uint32_t dwMode) override; + bool Open(const WideStringView& fileName, uint32_t dwMode) override; void Close() override; FX_FILESIZE GetSize() const override; FX_FILESIZE GetPosition() const override; diff --git a/core/fxcrt/cfx_seekablestreamproxy.cpp b/core/fxcrt/cfx_seekablestreamproxy.cpp index d3516e1794..6a6c6e6c3e 100644 --- a/core/fxcrt/cfx_seekablestreamproxy.cpp +++ b/core/fxcrt/cfx_seekablestreamproxy.cpp @@ -269,7 +269,7 @@ FX_STRSIZE CFX_SeekableStreamProxy::ReadString(wchar_t* pStr, return iMaxLength; } -void CFX_SeekableStreamProxy::WriteString(const CFX_WideStringC& str) { +void CFX_SeekableStreamProxy::WriteString(const WideStringView& str) { if (!m_IsWriteStream || str.GetLength() == 0 || m_wCodePage != FX_CODEPAGE_UTF8) { return; diff --git a/core/fxcrt/cfx_seekablestreamproxy.h b/core/fxcrt/cfx_seekablestreamproxy.h index 0e427fc79b..fc041b49b5 100644 --- a/core/fxcrt/cfx_seekablestreamproxy.h +++ b/core/fxcrt/cfx_seekablestreamproxy.h @@ -31,7 +31,7 @@ class CFX_SeekableStreamProxy : public CFX_Retainable { void Seek(From eSeek, FX_FILESIZE iOffset); FX_STRSIZE ReadString(wchar_t* pStr, FX_STRSIZE iMaxLength, bool* bEOS); - void WriteString(const CFX_WideStringC& str); + void WriteString(const WideStringView& str); uint16_t GetCodePage() const { return m_wCodePage; } void SetCodePage(uint16_t wCodePage); diff --git a/core/fxcrt/cfx_string_c_template.h b/core/fxcrt/cfx_string_c_template.h deleted file mode 100644 index 9123fc234b..0000000000 --- a/core/fxcrt/cfx_string_c_template.h +++ /dev/null @@ -1,240 +0,0 @@ -// Copyright 2016 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef CORE_FXCRT_CFX_STRING_C_TEMPLATE_H_ -#define CORE_FXCRT_CFX_STRING_C_TEMPLATE_H_ - -#include -#include -#include -#include -#include - -#include "core/fxcrt/cfx_unowned_ptr.h" -#include "core/fxcrt/fx_system.h" -#include "third_party/base/optional.h" -#include "third_party/base/stl_util.h" - -// An immutable string with caller-provided storage which must outlive the -// string itself. These are not necessarily nul-terminated, so that substring -// extraction (via the Mid(), Left(), and Right() methods) is copy-free. -template -class CFX_StringCTemplate { - public: - using CharType = T; - using UnsignedType = typename std::make_unsigned::type; - using const_iterator = const CharType*; - using const_reverse_iterator = std::reverse_iterator; - - CFX_StringCTemplate() : m_Ptr(nullptr), m_Length(0) {} - - // Deliberately implicit to avoid calling on every string literal. - // NOLINTNEXTLINE(runtime/explicit) - CFX_StringCTemplate(const CharType* ptr) - : m_Ptr(reinterpret_cast(ptr)), - m_Length(ptr ? FXSYS_len(ptr) : 0) {} - - CFX_StringCTemplate(const CharType* ptr, FX_STRSIZE len) - : m_Ptr(reinterpret_cast(ptr)), m_Length(len) {} - - template - CFX_StringCTemplate( - const UnsignedType* ptr, - FX_STRSIZE size, - typename std::enable_if::value>::type* = 0) - : m_Ptr(ptr), m_Length(size) {} - - // Deliberately implicit to avoid calling on every string literal. - // |ch| must be an lvalue that outlives the the CFX_StringCTemplate. - // NOLINTNEXTLINE(runtime/explicit) - CFX_StringCTemplate(CharType& ch) { - m_Ptr = reinterpret_cast(&ch); - m_Length = 1; - } - - CFX_StringCTemplate(const CFX_StringCTemplate& src) { - m_Ptr = src.m_Ptr; - m_Length = src.m_Length; - } - - // Any changes to |vec| invalidate the string. - explicit CFX_StringCTemplate(const std::vector& vec) { - m_Length = pdfium::CollectionSize(vec); - m_Ptr = m_Length ? vec.data() : nullptr; - } - - CFX_StringCTemplate& operator=(const CharType* src) { - m_Ptr = reinterpret_cast(src); - m_Length = src ? FXSYS_len(src) : 0; - return *this; - } - - CFX_StringCTemplate& operator=(const CFX_StringCTemplate& src) { - m_Ptr = src.m_Ptr; - m_Length = src.m_Length; - return *this; - } - - const_iterator begin() const { - return reinterpret_cast(m_Ptr.Get()); - } - const_iterator end() const { - return m_Ptr ? reinterpret_cast(m_Ptr.Get()) + m_Length - : nullptr; - } - - const_reverse_iterator rbegin() const { - return const_reverse_iterator(end()); - } - const_reverse_iterator rend() const { - return const_reverse_iterator(begin()); - } - - bool operator==(const CharType* ptr) const { - return FXSYS_len(ptr) == m_Length && - FXSYS_cmp(ptr, reinterpret_cast(m_Ptr.Get()), - m_Length) == 0; - } - bool operator==(const CFX_StringCTemplate& other) const { - return other.m_Length == m_Length && - FXSYS_cmp(reinterpret_cast(other.m_Ptr.Get()), - reinterpret_cast(m_Ptr.Get()), - m_Length) == 0; - } - bool operator!=(const CharType* ptr) const { return !(*this == ptr); } - bool operator!=(const CFX_StringCTemplate& other) const { - return !(*this == other); - } - - uint32_t GetID() const { - if (m_Length == 0) - return 0; - - uint32_t strid = 0; - FX_STRSIZE size = std::min(static_cast(4), m_Length); - for (FX_STRSIZE i = 0; i < size; i++) - strid = strid * 256 + m_Ptr.Get()[i]; - - return strid << ((4 - size) * 8); - } - - const UnsignedType* raw_str() const { return m_Ptr.Get(); } - const CharType* unterminated_c_str() const { - return reinterpret_cast(m_Ptr.Get()); - } - - FX_STRSIZE GetLength() const { return m_Length; } - bool IsEmpty() const { return m_Length == 0; } - bool IsValidIndex(FX_STRSIZE index) const { return index < GetLength(); } - bool IsValidLength(FX_STRSIZE length) const { return length <= GetLength(); } - - const UnsignedType& operator[](const FX_STRSIZE index) const { - ASSERT(IsValidIndex(index)); - return m_Ptr.Get()[index]; - } - - UnsignedType First() const { return GetLength() ? (*this)[0] : 0; } - - UnsignedType Last() const { - return GetLength() ? (*this)[GetLength() - 1] : 0; - } - - const CharType CharAt(const FX_STRSIZE index) const { - ASSERT(IsValidIndex(index)); - return static_cast(m_Ptr.Get()[index]); - } - - pdfium::Optional Find(CharType ch) const { - const UnsignedType* found = reinterpret_cast(FXSYS_chr( - reinterpret_cast(m_Ptr.Get()), ch, m_Length)); - - return found ? pdfium::Optional(found - m_Ptr.Get()) - : pdfium::Optional(); - } - - bool Contains(CharType ch) const { return Find(ch).has_value(); } - - CFX_StringCTemplate Mid(FX_STRSIZE first, FX_STRSIZE count) const { - if (!m_Ptr.Get()) - return CFX_StringCTemplate(); - - if (!IsValidIndex(first)) - return CFX_StringCTemplate(); - - if (count == 0 || !IsValidLength(count)) - return CFX_StringCTemplate(); - - if (!IsValidIndex(first + count - 1)) - return CFX_StringCTemplate(); - - return CFX_StringCTemplate(m_Ptr.Get() + first, count); - } - - CFX_StringCTemplate Left(FX_STRSIZE count) const { - if (count == 0 || !IsValidLength(count)) - return CFX_StringCTemplate(); - return Mid(0, count); - } - - CFX_StringCTemplate Right(FX_STRSIZE count) const { - if (count == 0 || !IsValidLength(count)) - return CFX_StringCTemplate(); - return Mid(GetLength() - count, count); - } - - CFX_StringCTemplate TrimmedRight(CharType ch) const { - if (IsEmpty()) - return CFX_StringCTemplate(); - - FX_STRSIZE pos = GetLength(); - while (pos && CharAt(pos - 1) == ch) - pos--; - - if (pos == 0) - return CFX_StringCTemplate(); - - return CFX_StringCTemplate(m_Ptr.Get(), pos); - } - - bool operator<(const CFX_StringCTemplate& that) const { - int result = FXSYS_cmp(reinterpret_cast(m_Ptr.Get()), - reinterpret_cast(that.m_Ptr.Get()), - std::min(m_Length, that.m_Length)); - return result < 0 || (result == 0 && m_Length < that.m_Length); - } - - bool operator>(const CFX_StringCTemplate& that) const { - int result = FXSYS_cmp(reinterpret_cast(m_Ptr.Get()), - reinterpret_cast(that.m_Ptr.Get()), - std::min(m_Length, that.m_Length)); - return result > 0 || (result == 0 && m_Length > that.m_Length); - } - - protected: - CFX_UnownedPtr m_Ptr; - FX_STRSIZE m_Length; - - private: - void* operator new(size_t) throw() { return nullptr; } -}; - -template -inline bool operator==(const T* lhs, const CFX_StringCTemplate& rhs) { - return rhs == lhs; -} - -template -inline bool operator!=(const T* lhs, const CFX_StringCTemplate& rhs) { - return rhs != lhs; -} - -extern template class CFX_StringCTemplate; -extern template class CFX_StringCTemplate; - -using CFX_ByteStringC = CFX_StringCTemplate; -using CFX_WideStringC = CFX_StringCTemplate; - -#endif // CORE_FXCRT_CFX_STRING_C_TEMPLATE_H_ diff --git a/core/fxcrt/cfx_string_pool_template.h b/core/fxcrt/cfx_string_pool_template.h index bfc1ce4bfb..b170a84127 100644 --- a/core/fxcrt/cfx_string_pool_template.h +++ b/core/fxcrt/cfx_string_pool_template.h @@ -21,10 +21,10 @@ class CFX_StringPoolTemplate { std::unordered_set m_Pool; }; -using CFX_ByteStringPool = CFX_StringPoolTemplate; -using CFX_WideStringPool = CFX_StringPoolTemplate; +using ByteStringPool = CFX_StringPoolTemplate; +using WideStringPool = CFX_StringPoolTemplate; -extern template class CFX_StringPoolTemplate; -extern template class CFX_StringPoolTemplate; +extern template class CFX_StringPoolTemplate; +extern template class CFX_StringPoolTemplate; #endif // CORE_FXCRT_CFX_STRING_POOL_TEMPLATE_H_ diff --git a/core/fxcrt/cfx_string_pool_template_unittest.cpp b/core/fxcrt/cfx_string_pool_template_unittest.cpp index a4e603c8fa..9a5ac5d3ed 100644 --- a/core/fxcrt/cfx_string_pool_template_unittest.cpp +++ b/core/fxcrt/cfx_string_pool_template_unittest.cpp @@ -7,22 +7,22 @@ #include "testing/gtest/include/gtest/gtest.h" TEST(fxcrt, ByteStringPool) { - CFX_ByteStringPool pool; + ByteStringPool pool; - CFX_ByteString null1; - CFX_ByteString null2; - CFX_ByteString goats1("goats"); - CFX_ByteString goats2("goats"); + ByteString null1; + ByteString null2; + ByteString goats1("goats"); + ByteString goats2("goats"); // Underlying storage, if non-null, is not shared. EXPECT_EQ(nullptr, null1.m_pData.Get()); EXPECT_EQ(nullptr, null2.m_pData.Get()); EXPECT_NE(goats1.m_pData, goats2.m_pData); - CFX_ByteString interned_null1 = pool.Intern(null1); - CFX_ByteString interned_null2 = pool.Intern(null2); - CFX_ByteString interned_goats1 = pool.Intern(goats1); - CFX_ByteString interned_goats2 = pool.Intern(goats2); + ByteString interned_null1 = pool.Intern(null1); + ByteString interned_null2 = pool.Intern(null2); + ByteString interned_goats1 = pool.Intern(goats1); + ByteString interned_goats2 = pool.Intern(goats2); // Strings are logically equal after being interned. EXPECT_EQ(null1, interned_null1); @@ -37,10 +37,10 @@ TEST(fxcrt, ByteStringPool) { EXPECT_EQ(goats1.m_pData, interned_goats2.m_pData); pool.Clear(); - CFX_ByteString reinterned_null2 = pool.Intern(null2); - CFX_ByteString reinterned_null1 = pool.Intern(null2); - CFX_ByteString reinterned_goats2 = pool.Intern(goats2); - CFX_ByteString reinterned_goats1 = pool.Intern(goats2); + ByteString reinterned_null2 = pool.Intern(null2); + ByteString reinterned_null1 = pool.Intern(null2); + ByteString reinterned_goats2 = pool.Intern(goats2); + ByteString reinterned_goats1 = pool.Intern(goats2); // After clearing pool, storage was re-interned using second strings. EXPECT_EQ(nullptr, interned_null1.m_pData.Get()); @@ -50,22 +50,22 @@ TEST(fxcrt, ByteStringPool) { } TEST(fxcrt, WideStringPool) { - CFX_WideStringPool pool; + WideStringPool pool; - CFX_WideString null1; - CFX_WideString null2; - CFX_WideString goats1(L"goats"); - CFX_WideString goats2(L"goats"); + WideString null1; + WideString null2; + WideString goats1(L"goats"); + WideString goats2(L"goats"); // Underlying storage, if non-null, is not shared. EXPECT_EQ(nullptr, null1.m_pData.Get()); EXPECT_EQ(nullptr, null2.m_pData.Get()); EXPECT_NE(goats1.m_pData, goats2.m_pData); - CFX_WideString interned_null1 = pool.Intern(null1); - CFX_WideString interned_null2 = pool.Intern(null2); - CFX_WideString interned_goats1 = pool.Intern(goats1); - CFX_WideString interned_goats2 = pool.Intern(goats2); + WideString interned_null1 = pool.Intern(null1); + WideString interned_null2 = pool.Intern(null2); + WideString interned_goats1 = pool.Intern(goats1); + WideString interned_goats2 = pool.Intern(goats2); // Strings are logically equal after being interned. EXPECT_EQ(null1, interned_null1); @@ -80,10 +80,10 @@ TEST(fxcrt, WideStringPool) { EXPECT_EQ(goats1.m_pData, interned_goats2.m_pData); pool.Clear(); - CFX_WideString reinterned_null2 = pool.Intern(null2); - CFX_WideString reinterned_null1 = pool.Intern(null2); - CFX_WideString reinterned_goats2 = pool.Intern(goats2); - CFX_WideString reinterned_goats1 = pool.Intern(goats2); + WideString reinterned_null2 = pool.Intern(null2); + WideString reinterned_null1 = pool.Intern(null2); + WideString reinterned_goats2 = pool.Intern(goats2); + WideString reinterned_goats1 = pool.Intern(goats2); // After clearing pool, storage was re-interned using second strings. EXPECT_EQ(nullptr, interned_null1.m_pData.Get()); diff --git a/core/fxcrt/cfx_utf8decoder.h b/core/fxcrt/cfx_utf8decoder.h index dcf5ef796a..1cafbe4472 100644 --- a/core/fxcrt/cfx_utf8decoder.h +++ b/core/fxcrt/cfx_utf8decoder.h @@ -17,7 +17,7 @@ class CFX_UTF8Decoder { void Input(uint8_t byte); void AppendCodePoint(uint32_t ch); void ClearStatus() { m_PendingBytes = 0; } - CFX_WideStringC GetResult() const { return m_Buffer.AsStringC(); } + WideStringView GetResult() const { return m_Buffer.AsStringView(); } private: int m_PendingBytes; diff --git a/core/fxcrt/cfx_widestring.cpp b/core/fxcrt/cfx_widestring.cpp deleted file mode 100644 index aadd1a29ed..0000000000 --- a/core/fxcrt/cfx_widestring.cpp +++ /dev/null @@ -1,1055 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "core/fxcrt/cfx_widestring.h" - -#include - -#include -#include -#include - -#include "core/fxcrt/cfx_string_pool_template.h" -#include "core/fxcrt/cfx_utf8decoder.h" -#include "core/fxcrt/fx_codepage.h" -#include "core/fxcrt/fx_extension.h" -#include "core/fxcrt/fx_safe_types.h" -#include "third_party/base/numerics/safe_math.h" -#include "third_party/base/stl_util.h" - -template class CFX_StringDataTemplate; -template class CFX_StringCTemplate; -template class CFX_StringPoolTemplate; -template struct std::hash; - -#define FORCE_ANSI 0x10000 -#define FORCE_UNICODE 0x20000 -#define FORCE_INT64 0x40000 - -namespace { - -const wchar_t* FX_wcsstr(const wchar_t* haystack, - int haystack_len, - const wchar_t* needle, - int needle_len) { - if (needle_len > haystack_len || needle_len == 0) { - return nullptr; - } - const wchar_t* end_ptr = haystack + haystack_len - needle_len; - while (haystack <= end_ptr) { - int i = 0; - while (1) { - if (haystack[i] != needle[i]) { - break; - } - i++; - if (i == needle_len) { - return haystack; - } - } - haystack++; - } - return nullptr; -} - -pdfium::Optional GuessSizeForVSWPrintf(const wchar_t* pFormat, - va_list argList) { - FX_STRSIZE nMaxLen = 0; - for (const wchar_t* pStr = pFormat; *pStr != 0; pStr++) { - if (*pStr != '%' || *(pStr = pStr + 1) == '%') { - ++nMaxLen; - continue; - } - int nItemLen = 0; - int nWidth = 0; - for (; *pStr != 0; pStr++) { - if (*pStr == '#') { - nMaxLen += 2; - } else if (*pStr == '*') { - nWidth = va_arg(argList, int); - } else if (*pStr != '-' && *pStr != '+' && *pStr != '0' && *pStr != ' ') { - break; - } - } - if (nWidth == 0) { - nWidth = FXSYS_wtoi(pStr); - while (std::iswdigit(*pStr)) - ++pStr; - } - if (nWidth < 0 || nWidth > 128 * 1024) - return pdfium::Optional(); - int nPrecision = 0; - if (*pStr == '.') { - pStr++; - if (*pStr == '*') { - nPrecision = va_arg(argList, int); - pStr++; - } else { - nPrecision = FXSYS_wtoi(pStr); - while (std::iswdigit(*pStr)) - ++pStr; - } - } - if (nPrecision < 0 || nPrecision > 128 * 1024) - return pdfium::Optional(); - int nModifier = 0; - if (*pStr == L'I' && *(pStr + 1) == L'6' && *(pStr + 2) == L'4') { - pStr += 3; - nModifier = FORCE_INT64; - } else { - switch (*pStr) { - case 'h': - nModifier = FORCE_ANSI; - pStr++; - break; - case 'l': - nModifier = FORCE_UNICODE; - pStr++; - break; - case 'F': - case 'N': - case 'L': - pStr++; - break; - } - } - switch (*pStr | nModifier) { - case 'c': - case 'C': - nItemLen = 2; - va_arg(argList, int); - break; - case 'c' | FORCE_ANSI: - case 'C' | FORCE_ANSI: - nItemLen = 2; - va_arg(argList, int); - break; - case 'c' | FORCE_UNICODE: - case 'C' | FORCE_UNICODE: - nItemLen = 2; - va_arg(argList, int); - break; - case 's': { - const wchar_t* pstrNextArg = va_arg(argList, const wchar_t*); - if (pstrNextArg) { - nItemLen = FXSYS_wcslen(pstrNextArg); - if (nItemLen < 1) { - nItemLen = 1; - } - } else { - nItemLen = 6; - } - } break; - case 'S': { - const char* pstrNextArg = va_arg(argList, const char*); - if (pstrNextArg) { - nItemLen = FXSYS_strlen(pstrNextArg); - if (nItemLen < 1) { - nItemLen = 1; - } - } else { - nItemLen = 6; - } - } break; - case 's' | FORCE_ANSI: - case 'S' | FORCE_ANSI: { - const char* pstrNextArg = va_arg(argList, const char*); - if (pstrNextArg) { - nItemLen = FXSYS_strlen(pstrNextArg); - if (nItemLen < 1) { - nItemLen = 1; - } - } else { - nItemLen = 6; - } - } break; - case 's' | FORCE_UNICODE: - case 'S' | FORCE_UNICODE: { - const wchar_t* pstrNextArg = va_arg(argList, wchar_t*); - if (pstrNextArg) { - nItemLen = FXSYS_wcslen(pstrNextArg); - if (nItemLen < 1) { - nItemLen = 1; - } - } else { - nItemLen = 6; - } - } break; - } - if (nItemLen != 0) { - if (nPrecision != 0 && nItemLen > nPrecision) { - nItemLen = nPrecision; - } - if (nItemLen < nWidth) { - nItemLen = nWidth; - } - } else { - switch (*pStr) { - case 'd': - case 'i': - case 'u': - case 'x': - case 'X': - case 'o': - if (nModifier & FORCE_INT64) { - va_arg(argList, int64_t); - } else { - va_arg(argList, int); - } - nItemLen = 32; - if (nItemLen < nWidth + nPrecision) { - nItemLen = nWidth + nPrecision; - } - break; - case 'a': - case 'A': - case 'e': - case 'E': - case 'g': - case 'G': - va_arg(argList, double); - nItemLen = 128; - if (nItemLen < nWidth + nPrecision) { - nItemLen = nWidth + nPrecision; - } - break; - case 'f': - if (nWidth + nPrecision > 100) { - nItemLen = nPrecision + nWidth + 128; - } else { - double f; - char pszTemp[256]; - f = va_arg(argList, double); - FXSYS_snprintf(pszTemp, sizeof(pszTemp), "%*.*f", nWidth, - nPrecision + 6, f); - nItemLen = FXSYS_strlen(pszTemp); - } - break; - case 'p': - va_arg(argList, void*); - nItemLen = 32; - if (nItemLen < nWidth + nPrecision) { - nItemLen = nWidth + nPrecision; - } - break; - case 'n': - va_arg(argList, int*); - break; - } - } - nMaxLen += nItemLen; - } - nMaxLen += 32; // Fudge factor. - return pdfium::Optional(nMaxLen); -} - -#ifndef NDEBUG -bool IsValidCodePage(uint16_t codepage) { - switch (codepage) { - case FX_CODEPAGE_DefANSI: - case FX_CODEPAGE_ShiftJIS: - case FX_CODEPAGE_ChineseSimplified: - case FX_CODEPAGE_Hangul: - case FX_CODEPAGE_ChineseTraditional: - return true; - default: - return false; - } -} -#endif - -CFX_WideString GetWideString(uint16_t codepage, const CFX_ByteStringC& bstr) { - ASSERT(IsValidCodePage(codepage)); - - int src_len = bstr.GetLength(); - int dest_len = FXSYS_MultiByteToWideChar( - codepage, 0, bstr.unterminated_c_str(), src_len, nullptr, 0); - if (!dest_len) - return CFX_WideString(); - - CFX_WideString wstr; - wchar_t* dest_buf = wstr.GetBuffer(dest_len); - FXSYS_MultiByteToWideChar(codepage, 0, bstr.unterminated_c_str(), src_len, - dest_buf, dest_len); - wstr.ReleaseBuffer(dest_len); - return wstr; -} - -} // namespace - -static_assert(sizeof(CFX_WideString) <= sizeof(wchar_t*), - "Strings must not require more space than pointers"); - -CFX_WideString::CFX_WideString() {} - -CFX_WideString::CFX_WideString(const CFX_WideString& other) - : m_pData(other.m_pData) {} - -CFX_WideString::CFX_WideString(CFX_WideString&& other) noexcept { - m_pData.Swap(other.m_pData); -} - -CFX_WideString::CFX_WideString(const wchar_t* pStr, FX_STRSIZE nLen) { - if (nLen) - m_pData.Reset(StringData::Create(pStr, nLen)); -} - -CFX_WideString::CFX_WideString(wchar_t ch) { - m_pData.Reset(StringData::Create(1)); - m_pData->m_String[0] = ch; -} - -CFX_WideString::CFX_WideString(const wchar_t* ptr) - : CFX_WideString(ptr, ptr ? FXSYS_wcslen(ptr) : 0) {} - -CFX_WideString::CFX_WideString(const CFX_WideStringC& stringSrc) { - if (!stringSrc.IsEmpty()) { - m_pData.Reset(StringData::Create(stringSrc.unterminated_c_str(), - stringSrc.GetLength())); - } -} - -CFX_WideString::CFX_WideString(const CFX_WideStringC& str1, - const CFX_WideStringC& str2) { - FX_SAFE_STRSIZE nSafeLen = str1.GetLength(); - nSafeLen += str2.GetLength(); - - FX_STRSIZE nNewLen = nSafeLen.ValueOrDie(); - if (nNewLen == 0) - return; - - m_pData.Reset(StringData::Create(nNewLen)); - m_pData->CopyContents(str1.unterminated_c_str(), str1.GetLength()); - m_pData->CopyContentsAt(str1.GetLength(), str2.unterminated_c_str(), - str2.GetLength()); -} - -CFX_WideString::CFX_WideString( - const std::initializer_list& list) { - FX_SAFE_STRSIZE nSafeLen = 0; - for (const auto& item : list) - nSafeLen += item.GetLength(); - - FX_STRSIZE nNewLen = nSafeLen.ValueOrDie(); - if (nNewLen == 0) - return; - - m_pData.Reset(StringData::Create(nNewLen)); - - FX_STRSIZE nOffset = 0; - for (const auto& item : list) { - m_pData->CopyContentsAt(nOffset, item.unterminated_c_str(), - item.GetLength()); - nOffset += item.GetLength(); - } -} - -CFX_WideString::~CFX_WideString() {} - -const CFX_WideString& CFX_WideString::operator=(const wchar_t* pStr) { - if (!pStr || !pStr[0]) - clear(); - else - AssignCopy(pStr, FXSYS_wcslen(pStr)); - - return *this; -} - -const CFX_WideString& CFX_WideString::operator=( - const CFX_WideStringC& stringSrc) { - if (stringSrc.IsEmpty()) - clear(); - else - AssignCopy(stringSrc.unterminated_c_str(), stringSrc.GetLength()); - - return *this; -} - -const CFX_WideString& CFX_WideString::operator=( - const CFX_WideString& stringSrc) { - if (m_pData != stringSrc.m_pData) - m_pData = stringSrc.m_pData; - - return *this; -} - -const CFX_WideString& CFX_WideString::operator+=(const wchar_t* pStr) { - if (pStr) - Concat(pStr, FXSYS_wcslen(pStr)); - - return *this; -} - -const CFX_WideString& CFX_WideString::operator+=(wchar_t ch) { - Concat(&ch, 1); - return *this; -} - -const CFX_WideString& CFX_WideString::operator+=(const CFX_WideString& str) { - if (str.m_pData) - Concat(str.m_pData->m_String, str.m_pData->m_nDataLength); - - return *this; -} - -const CFX_WideString& CFX_WideString::operator+=(const CFX_WideStringC& str) { - if (!str.IsEmpty()) - Concat(str.unterminated_c_str(), str.GetLength()); - - return *this; -} - -bool CFX_WideString::operator==(const wchar_t* ptr) const { - if (!m_pData) - return !ptr || !ptr[0]; - - if (!ptr) - return m_pData->m_nDataLength == 0; - - return wcslen(ptr) == m_pData->m_nDataLength && - wmemcmp(ptr, m_pData->m_String, m_pData->m_nDataLength) == 0; -} - -bool CFX_WideString::operator==(const CFX_WideStringC& str) const { - if (!m_pData) - return str.IsEmpty(); - - return m_pData->m_nDataLength == str.GetLength() && - wmemcmp(m_pData->m_String, str.unterminated_c_str(), - str.GetLength()) == 0; -} - -bool CFX_WideString::operator==(const CFX_WideString& other) const { - if (m_pData == other.m_pData) - return true; - - if (IsEmpty()) - return other.IsEmpty(); - - if (other.IsEmpty()) - return false; - - return other.m_pData->m_nDataLength == m_pData->m_nDataLength && - wmemcmp(other.m_pData->m_String, m_pData->m_String, - m_pData->m_nDataLength) == 0; -} - -bool CFX_WideString::operator<(const CFX_WideString& str) const { - if (m_pData == str.m_pData) - return false; - - int result = - wmemcmp(c_str(), str.c_str(), std::min(GetLength(), str.GetLength())); - return result < 0 || (result == 0 && GetLength() < str.GetLength()); -} - -void CFX_WideString::AssignCopy(const wchar_t* pSrcData, FX_STRSIZE nSrcLen) { - AllocBeforeWrite(nSrcLen); - m_pData->CopyContents(pSrcData, nSrcLen); - m_pData->m_nDataLength = nSrcLen; -} - -void CFX_WideString::ReallocBeforeWrite(FX_STRSIZE nNewLength) { - if (m_pData && m_pData->CanOperateInPlace(nNewLength)) - return; - - if (nNewLength == 0) { - clear(); - return; - } - - CFX_RetainPtr pNewData(StringData::Create(nNewLength)); - if (m_pData) { - FX_STRSIZE nCopyLength = std::min(m_pData->m_nDataLength, nNewLength); - pNewData->CopyContents(m_pData->m_String, nCopyLength); - pNewData->m_nDataLength = nCopyLength; - } else { - pNewData->m_nDataLength = 0; - } - pNewData->m_String[pNewData->m_nDataLength] = 0; - m_pData.Swap(pNewData); -} - -void CFX_WideString::AllocBeforeWrite(FX_STRSIZE nNewLength) { - if (m_pData && m_pData->CanOperateInPlace(nNewLength)) - return; - - if (nNewLength == 0) { - clear(); - return; - } - - m_pData.Reset(StringData::Create(nNewLength)); -} - -void CFX_WideString::ReleaseBuffer(FX_STRSIZE nNewLength) { - if (!m_pData) - return; - - nNewLength = std::min(nNewLength, m_pData->m_nAllocLength); - if (nNewLength == 0) { - clear(); - return; - } - - ASSERT(m_pData->m_nRefs == 1); - m_pData->m_nDataLength = nNewLength; - m_pData->m_String[nNewLength] = 0; - if (m_pData->m_nAllocLength - nNewLength >= 32) { - // Over arbitrary threshold, so pay the price to relocate. Force copy to - // always occur by holding a second reference to the string. - CFX_WideString preserve(*this); - ReallocBeforeWrite(nNewLength); - } -} - -void CFX_WideString::Reserve(FX_STRSIZE len) { - GetBuffer(len); -} - -wchar_t* CFX_WideString::GetBuffer(FX_STRSIZE nMinBufLength) { - if (!m_pData) { - if (nMinBufLength == 0) - return nullptr; - - m_pData.Reset(StringData::Create(nMinBufLength)); - m_pData->m_nDataLength = 0; - m_pData->m_String[0] = 0; - return m_pData->m_String; - } - - if (m_pData->CanOperateInPlace(nMinBufLength)) - return m_pData->m_String; - - nMinBufLength = std::max(nMinBufLength, m_pData->m_nDataLength); - if (nMinBufLength == 0) - return nullptr; - - CFX_RetainPtr pNewData(StringData::Create(nMinBufLength)); - pNewData->CopyContents(*m_pData); - pNewData->m_nDataLength = m_pData->m_nDataLength; - m_pData.Swap(pNewData); - return m_pData->m_String; -} - -FX_STRSIZE CFX_WideString::Delete(FX_STRSIZE index, FX_STRSIZE count) { - if (!m_pData) - return 0; - - FX_STRSIZE old_length = m_pData->m_nDataLength; - if (count == 0 || - index != pdfium::clamp(index, static_cast(0), old_length)) - return old_length; - - FX_STRSIZE removal_length = index + count; - if (removal_length > old_length) - return old_length; - - ReallocBeforeWrite(old_length); - FX_STRSIZE chars_to_copy = old_length - removal_length + 1; - wmemmove(m_pData->m_String + index, m_pData->m_String + removal_length, - chars_to_copy); - m_pData->m_nDataLength = old_length - count; - return m_pData->m_nDataLength; -} - -void CFX_WideString::Concat(const wchar_t* pSrcData, FX_STRSIZE nSrcLen) { - if (!pSrcData || nSrcLen == 0) - return; - - if (!m_pData) { - m_pData.Reset(StringData::Create(pSrcData, nSrcLen)); - return; - } - - if (m_pData->CanOperateInPlace(m_pData->m_nDataLength + nSrcLen)) { - m_pData->CopyContentsAt(m_pData->m_nDataLength, pSrcData, nSrcLen); - m_pData->m_nDataLength += nSrcLen; - return; - } - - CFX_RetainPtr pNewData( - StringData::Create(m_pData->m_nDataLength + nSrcLen)); - pNewData->CopyContents(*m_pData); - pNewData->CopyContentsAt(m_pData->m_nDataLength, pSrcData, nSrcLen); - m_pData.Swap(pNewData); -} - -CFX_ByteString CFX_WideString::UTF8Encode() const { - return FX_UTF8Encode(AsStringC()); -} - -CFX_ByteString CFX_WideString::UTF16LE_Encode() const { - if (!m_pData) { - return CFX_ByteString("\0\0", 2); - } - int len = m_pData->m_nDataLength; - CFX_ByteString result; - char* buffer = result.GetBuffer(len * 2 + 2); - for (int i = 0; i < len; i++) { - buffer[i * 2] = m_pData->m_String[i] & 0xff; - buffer[i * 2 + 1] = m_pData->m_String[i] >> 8; - } - buffer[len * 2] = 0; - buffer[len * 2 + 1] = 0; - result.ReleaseBuffer(len * 2 + 2); - return result; -} - -CFX_WideString CFX_WideString::Mid(FX_STRSIZE first, FX_STRSIZE count) const { - if (!m_pData) - return CFX_WideString(); - - if (!IsValidIndex(first)) - return CFX_WideString(); - - if (count == 0 || !IsValidLength(count)) - return CFX_WideString(); - - if (!IsValidIndex(first + count - 1)) - return CFX_WideString(); - - if (first == 0 && count == GetLength()) - return *this; - - CFX_WideString dest; - AllocCopy(dest, count, first); - return dest; -} - -CFX_WideString CFX_WideString::Left(FX_STRSIZE count) const { - if (count == 0 || !IsValidLength(count)) - return CFX_WideString(); - return Mid(0, count); -} - -CFX_WideString CFX_WideString::Right(FX_STRSIZE count) const { - if (count == 0 || !IsValidLength(count)) - return CFX_WideString(); - return Mid(GetLength() - count, count); -} - -void CFX_WideString::AllocCopy(CFX_WideString& dest, - FX_STRSIZE nCopyLen, - FX_STRSIZE nCopyIndex) const { - if (nCopyLen == 0) - return; - - CFX_RetainPtr pNewData( - StringData::Create(m_pData->m_String + nCopyIndex, nCopyLen)); - dest.m_pData.Swap(pNewData); -} - -bool CFX_WideString::TryVSWPrintf(FX_STRSIZE size, - const wchar_t* pFormat, - va_list argList) { - GetBuffer(size); - if (!m_pData) - return true; - - // In the following two calls, there's always space in the buffer for - // a terminating NUL that's not included in nMaxLen. - // For vswprintf(), MSAN won't untaint the buffer on a truncated write's - // -1 return code even though the buffer is written. Probably just as well - // not to trust the vendor's implementation to write anything anyways. - // See https://crbug.com/705912. - memset(m_pData->m_String, 0, (size + 1) * sizeof(wchar_t)); - int ret = vswprintf(m_pData->m_String, size + 1, pFormat, argList); - bool bSufficientBuffer = ret >= 0 || m_pData->m_String[size - 1] == 0; - ReleaseBuffer(GetStringLength()); - return bSufficientBuffer; -} - -void CFX_WideString::FormatV(const wchar_t* format, va_list argList) { - va_list argListCopy; - va_copy(argListCopy, argList); - int maxLen = vswprintf(nullptr, 0, format, argListCopy); - va_end(argListCopy); - if (maxLen <= 0) { - va_copy(argListCopy, argList); - auto guess = GuessSizeForVSWPrintf(format, argListCopy); - va_end(argListCopy); - if (!guess.has_value()) - return; - maxLen = pdfium::base::checked_cast(guess.value()); - } - while (maxLen < 32 * 1024) { - va_copy(argListCopy, argList); - bool bSufficientBuffer = - TryVSWPrintf(static_cast(maxLen), format, argListCopy); - va_end(argListCopy); - if (bSufficientBuffer) - break; - maxLen *= 2; - } -} - -void CFX_WideString::Format(const wchar_t* pFormat, ...) { - va_list argList; - va_start(argList, pFormat); - FormatV(pFormat, argList); - va_end(argList); -} - -FX_STRSIZE CFX_WideString::Insert(FX_STRSIZE location, wchar_t ch) { - const FX_STRSIZE cur_length = m_pData ? m_pData->m_nDataLength : 0; - if (!IsValidLength(location)) - return cur_length; - - const FX_STRSIZE new_length = cur_length + 1; - ReallocBeforeWrite(new_length); - wmemmove(m_pData->m_String + location + 1, m_pData->m_String + location, - new_length - location); - m_pData->m_String[location] = ch; - m_pData->m_nDataLength = new_length; - return new_length; -} - -pdfium::Optional CFX_WideString::Find(wchar_t ch, - FX_STRSIZE start) const { - if (!m_pData) - return pdfium::Optional(); - - if (!IsValidIndex(start)) - return pdfium::Optional(); - - const wchar_t* pStr = - wmemchr(m_pData->m_String + start, ch, m_pData->m_nDataLength - start); - return pStr ? pdfium::Optional( - static_cast(pStr - m_pData->m_String)) - : pdfium::Optional(); -} - -pdfium::Optional CFX_WideString::Find(const CFX_WideStringC& subStr, - FX_STRSIZE start) const { - if (!m_pData) - return pdfium::Optional(); - - if (!IsValidIndex(start)) - return pdfium::Optional(); - - const wchar_t* pStr = - FX_wcsstr(m_pData->m_String + start, m_pData->m_nDataLength - start, - subStr.unterminated_c_str(), subStr.GetLength()); - return pStr ? pdfium::Optional( - static_cast(pStr - m_pData->m_String)) - : pdfium::Optional(); -} - -void CFX_WideString::MakeLower() { - if (!m_pData) - return; - - ReallocBeforeWrite(m_pData->m_nDataLength); - FXSYS_wcslwr(m_pData->m_String); -} - -void CFX_WideString::MakeUpper() { - if (!m_pData) - return; - - ReallocBeforeWrite(m_pData->m_nDataLength); - FXSYS_wcsupr(m_pData->m_String); -} - -FX_STRSIZE CFX_WideString::Remove(wchar_t chRemove) { - if (!m_pData || m_pData->m_nDataLength < 1) - return 0; - - wchar_t* pstrSource = m_pData->m_String; - wchar_t* pstrEnd = m_pData->m_String + m_pData->m_nDataLength; - while (pstrSource < pstrEnd) { - if (*pstrSource == chRemove) - break; - pstrSource++; - } - if (pstrSource == pstrEnd) - return 0; - - ptrdiff_t copied = pstrSource - m_pData->m_String; - ReallocBeforeWrite(m_pData->m_nDataLength); - pstrSource = m_pData->m_String + copied; - pstrEnd = m_pData->m_String + m_pData->m_nDataLength; - - wchar_t* pstrDest = pstrSource; - while (pstrSource < pstrEnd) { - if (*pstrSource != chRemove) { - *pstrDest = *pstrSource; - pstrDest++; - } - pstrSource++; - } - - *pstrDest = 0; - FX_STRSIZE count = static_cast(pstrSource - pstrDest); - m_pData->m_nDataLength -= count; - return count; -} - -FX_STRSIZE CFX_WideString::Replace(const CFX_WideStringC& pOld, - const CFX_WideStringC& pNew) { - if (!m_pData || pOld.IsEmpty()) - return 0; - - FX_STRSIZE nSourceLen = pOld.GetLength(); - FX_STRSIZE nReplacementLen = pNew.GetLength(); - FX_STRSIZE count = 0; - const wchar_t* pStart = m_pData->m_String; - wchar_t* pEnd = m_pData->m_String + m_pData->m_nDataLength; - while (1) { - const wchar_t* pTarget = FX_wcsstr(pStart, (FX_STRSIZE)(pEnd - pStart), - pOld.unterminated_c_str(), nSourceLen); - if (!pTarget) - break; - - count++; - pStart = pTarget + nSourceLen; - } - if (count == 0) - return 0; - - FX_STRSIZE nNewLength = - m_pData->m_nDataLength + (nReplacementLen - nSourceLen) * count; - - if (nNewLength == 0) { - clear(); - return count; - } - - CFX_RetainPtr pNewData(StringData::Create(nNewLength)); - pStart = m_pData->m_String; - wchar_t* pDest = pNewData->m_String; - for (FX_STRSIZE i = 0; i < count; i++) { - const wchar_t* pTarget = FX_wcsstr(pStart, (FX_STRSIZE)(pEnd - pStart), - pOld.unterminated_c_str(), nSourceLen); - wmemcpy(pDest, pStart, pTarget - pStart); - pDest += pTarget - pStart; - wmemcpy(pDest, pNew.unterminated_c_str(), pNew.GetLength()); - pDest += pNew.GetLength(); - pStart = pTarget + nSourceLen; - } - wmemcpy(pDest, pStart, pEnd - pStart); - m_pData.Swap(pNewData); - return count; -} - -// static -CFX_WideString CFX_WideString::FromLocal(const CFX_ByteStringC& str) { - return FromCodePage(str, 0); -} - -// static -CFX_WideString CFX_WideString::FromCodePage(const CFX_ByteStringC& str, - uint16_t codepage) { - return GetWideString(codepage, str); -} - -// static -CFX_WideString CFX_WideString::FromUTF8(const CFX_ByteStringC& str) { - if (str.IsEmpty()) - return CFX_WideString(); - - CFX_UTF8Decoder decoder; - for (FX_STRSIZE i = 0; i < str.GetLength(); i++) - decoder.Input(str[i]); - - return CFX_WideString(decoder.GetResult()); -} - -// static -CFX_WideString CFX_WideString::FromUTF16LE(const unsigned short* wstr, - FX_STRSIZE wlen) { - if (!wstr || wlen == 0) { - return CFX_WideString(); - } - - CFX_WideString result; - wchar_t* buf = result.GetBuffer(wlen); - for (FX_STRSIZE i = 0; i < wlen; i++) { - buf[i] = wstr[i]; - } - result.ReleaseBuffer(wlen); - return result; -} - -void CFX_WideString::SetAt(FX_STRSIZE index, wchar_t c) { - ASSERT(IsValidIndex(index)); - ReallocBeforeWrite(m_pData->m_nDataLength); - m_pData->m_String[index] = c; -} - -int CFX_WideString::Compare(const wchar_t* lpsz) const { - if (m_pData) - return wcscmp(m_pData->m_String, lpsz); - return (!lpsz || lpsz[0] == 0) ? 0 : -1; -} - -int CFX_WideString::Compare(const CFX_WideString& str) const { - if (!m_pData) { - if (!str.m_pData) { - return 0; - } - return -1; - } - if (!str.m_pData) { - return 1; - } - FX_STRSIZE this_len = m_pData->m_nDataLength; - FX_STRSIZE that_len = str.m_pData->m_nDataLength; - FX_STRSIZE min_len = std::min(this_len, that_len); - for (FX_STRSIZE i = 0; i < min_len; i++) { - if (m_pData->m_String[i] < str.m_pData->m_String[i]) { - return -1; - } - if (m_pData->m_String[i] > str.m_pData->m_String[i]) { - return 1; - } - } - if (this_len < that_len) { - return -1; - } - if (this_len > that_len) { - return 1; - } - return 0; -} - -int CFX_WideString::CompareNoCase(const wchar_t* lpsz) const { - if (!m_pData) { - return (!lpsz || lpsz[0] == 0) ? 0 : -1; - } - return FXSYS_wcsicmp(m_pData->m_String, lpsz); -} - -FX_STRSIZE CFX_WideString::WStringLength(const unsigned short* str) { - FX_STRSIZE len = 0; - if (str) - while (str[len]) - len++; - return len; -} - -void CFX_WideString::TrimRight(const CFX_WideStringC& pTargets) { - if (IsEmpty() || pTargets.IsEmpty()) - return; - - FX_STRSIZE pos = GetLength(); - while (pos && pTargets.Contains(m_pData->m_String[pos - 1])) - pos--; - - if (pos < m_pData->m_nDataLength) { - ReallocBeforeWrite(m_pData->m_nDataLength); - m_pData->m_String[pos] = 0; - m_pData->m_nDataLength = pos; - } -} - -void CFX_WideString::TrimRight(wchar_t chTarget) { - wchar_t str[2] = {chTarget, 0}; - TrimRight(str); -} - -void CFX_WideString::TrimRight() { - TrimRight(L"\x09\x0a\x0b\x0c\x0d\x20"); -} - -void CFX_WideString::TrimLeft(const CFX_WideStringC& pTargets) { - if (!m_pData || pTargets.IsEmpty()) - return; - - FX_STRSIZE len = GetLength(); - if (len == 0) - return; - - FX_STRSIZE pos = 0; - while (pos < len) { - FX_STRSIZE i = 0; - while (i < pTargets.GetLength() && - pTargets.CharAt(i) != m_pData->m_String[pos]) { - i++; - } - if (i == pTargets.GetLength()) { - break; - } - pos++; - } - if (!pos) - return; - - ReallocBeforeWrite(len); - FX_STRSIZE nDataLength = len - pos; - memmove(m_pData->m_String, m_pData->m_String + pos, - (nDataLength + 1) * sizeof(wchar_t)); - m_pData->m_nDataLength = nDataLength; -} - -void CFX_WideString::TrimLeft(wchar_t chTarget) { - wchar_t str[2] = {chTarget, 0}; - TrimLeft(str); -} - -void CFX_WideString::TrimLeft() { - TrimLeft(L"\x09\x0a\x0b\x0c\x0d\x20"); -} -float FX_wtof(const wchar_t* str, int len) { - if (len == 0) { - return 0.0; - } - int cc = 0; - bool bNegative = false; - if (str[0] == '+') { - cc++; - } else if (str[0] == '-') { - bNegative = true; - cc++; - } - int integer = 0; - while (cc < len) { - if (str[cc] == '.') { - break; - } - integer = integer * 10 + FXSYS_DecimalCharToInt(str[cc]); - cc++; - } - float fraction = 0; - if (str[cc] == '.') { - cc++; - float scale = 0.1f; - while (cc < len) { - fraction += scale * FXSYS_DecimalCharToInt(str[cc]); - scale *= 0.1f; - cc++; - } - } - fraction += static_cast(integer); - return bNegative ? -fraction : fraction; -} - -int CFX_WideString::GetInteger() const { - return m_pData ? FXSYS_wtoi(m_pData->m_String) : 0; -} - -float CFX_WideString::GetFloat() const { - return m_pData ? FX_wtof(m_pData->m_String, m_pData->m_nDataLength) : 0.0f; -} - -std::wostream& operator<<(std::wostream& os, const CFX_WideString& str) { - return os.write(str.c_str(), str.GetLength()); -} - -std::ostream& operator<<(std::ostream& os, const CFX_WideString& str) { - os << str.UTF8Encode(); - return os; -} - -std::wostream& operator<<(std::wostream& os, const CFX_WideStringC& str) { - return os.write(str.unterminated_c_str(), str.GetLength()); -} - -std::ostream& operator<<(std::ostream& os, const CFX_WideStringC& str) { - os << FX_UTF8Encode(str); - return os; -} diff --git a/core/fxcrt/cfx_widestring.h b/core/fxcrt/cfx_widestring.h deleted file mode 100644 index 595615a0b2..0000000000 --- a/core/fxcrt/cfx_widestring.h +++ /dev/null @@ -1,276 +0,0 @@ -// Copyright 2017 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef CORE_FXCRT_CFX_WIDESTRING_H_ -#define CORE_FXCRT_CFX_WIDESTRING_H_ - -#include -#include -#include - -#include "core/fxcrt/cfx_retain_ptr.h" -#include "core/fxcrt/cfx_string_c_template.h" -#include "core/fxcrt/cfx_string_data_template.h" -#include "core/fxcrt/fx_memory.h" -#include "core/fxcrt/fx_system.h" -#include "third_party/base/optional.h" - -class CFX_ByteString; - -// A mutable string with shared buffers using copy-on-write semantics that -// avoids the cost of std::string's iterator stability guarantees. -class CFX_WideString { - public: - using CharType = wchar_t; - using const_iterator = const CharType*; - using const_reverse_iterator = std::reverse_iterator; - - CFX_WideString(); - CFX_WideString(const CFX_WideString& other); - CFX_WideString(CFX_WideString&& other) noexcept; - - // Deliberately implicit to avoid calling on every string literal. - // NOLINTNEXTLINE(runtime/explicit) - CFX_WideString(wchar_t ch); - // NOLINTNEXTLINE(runtime/explicit) - CFX_WideString(const wchar_t* ptr); - - // No implicit conversions from byte strings. - // NOLINTNEXTLINE(runtime/explicit) - CFX_WideString(char) = delete; - - CFX_WideString(const wchar_t* ptr, FX_STRSIZE len); - - explicit CFX_WideString(const CFX_WideStringC& str); - CFX_WideString(const CFX_WideStringC& str1, const CFX_WideStringC& str2); - CFX_WideString(const std::initializer_list& list); - - ~CFX_WideString(); - - static CFX_WideString FromLocal(const CFX_ByteStringC& str); - static CFX_WideString FromCodePage(const CFX_ByteStringC& str, - uint16_t codepage); - - static CFX_WideString FromUTF8(const CFX_ByteStringC& str); - static CFX_WideString FromUTF16LE(const unsigned short* str, FX_STRSIZE len); - - static FX_STRSIZE WStringLength(const unsigned short* str); - - // Explicit conversion to C-style wide string. - // Note: Any subsequent modification of |this| will invalidate the result. - const wchar_t* c_str() const { return m_pData ? m_pData->m_String : L""; } - - // Explicit conversion to CFX_WideStringC. - // Note: Any subsequent modification of |this| will invalidate the result. - CFX_WideStringC AsStringC() const { - return CFX_WideStringC(c_str(), GetLength()); - } - - // Note: Any subsequent modification of |this| will invalidate iterators. - const_iterator begin() const { return m_pData ? m_pData->m_String : nullptr; } - const_iterator end() const { - return m_pData ? m_pData->m_String + m_pData->m_nDataLength : nullptr; - } - - // Note: Any subsequent modification of |this| will invalidate iterators. - const_reverse_iterator rbegin() const { - return const_reverse_iterator(end()); - } - const_reverse_iterator rend() const { - return const_reverse_iterator(begin()); - } - - void clear() { m_pData.Reset(); } - - FX_STRSIZE GetLength() const { return m_pData ? m_pData->m_nDataLength : 0; } - FX_STRSIZE GetStringLength() const { - return m_pData ? FXSYS_wcslen(m_pData->m_String) : 0; - } - bool IsEmpty() const { return !GetLength(); } - bool IsValidIndex(FX_STRSIZE index) const { return index < GetLength(); } - bool IsValidLength(FX_STRSIZE length) const { return length <= GetLength(); } - - const CFX_WideString& operator=(const wchar_t* str); - const CFX_WideString& operator=(const CFX_WideString& stringSrc); - const CFX_WideString& operator=(const CFX_WideStringC& stringSrc); - - const CFX_WideString& operator+=(const wchar_t* str); - const CFX_WideString& operator+=(wchar_t ch); - const CFX_WideString& operator+=(const CFX_WideString& str); - const CFX_WideString& operator+=(const CFX_WideStringC& str); - - bool operator==(const wchar_t* ptr) const; - bool operator==(const CFX_WideStringC& str) const; - bool operator==(const CFX_WideString& other) const; - - bool operator!=(const wchar_t* ptr) const { return !(*this == ptr); } - bool operator!=(const CFX_WideStringC& str) const { return !(*this == str); } - bool operator!=(const CFX_WideString& other) const { - return !(*this == other); - } - - bool operator<(const CFX_WideString& str) const; - - CharType operator[](const FX_STRSIZE index) const { - ASSERT(IsValidIndex(index)); - return m_pData ? m_pData->m_String[index] : 0; - } - - CharType First() const { return GetLength() ? (*this)[0] : 0; } - CharType Last() const { return GetLength() ? (*this)[GetLength() - 1] : 0; } - - void SetAt(FX_STRSIZE index, wchar_t c); - - int Compare(const wchar_t* str) const; - int Compare(const CFX_WideString& str) const; - int CompareNoCase(const wchar_t* str) const; - - CFX_WideString Mid(FX_STRSIZE first, FX_STRSIZE count) const; - CFX_WideString Left(FX_STRSIZE count) const; - CFX_WideString Right(FX_STRSIZE count) const; - - FX_STRSIZE Insert(FX_STRSIZE index, wchar_t ch); - FX_STRSIZE InsertAtFront(wchar_t ch) { return Insert(0, ch); } - FX_STRSIZE InsertAtBack(wchar_t ch) { return Insert(GetLength(), ch); } - FX_STRSIZE Delete(FX_STRSIZE index, FX_STRSIZE count = 1); - - void Format(const wchar_t* lpszFormat, ...); - void FormatV(const wchar_t* lpszFormat, va_list argList); - - void MakeLower(); - void MakeUpper(); - - void TrimRight(); - void TrimRight(wchar_t chTarget); - void TrimRight(const CFX_WideStringC& pTargets); - - void TrimLeft(); - void TrimLeft(wchar_t chTarget); - void TrimLeft(const CFX_WideStringC& pTargets); - - void Reserve(FX_STRSIZE len); - wchar_t* GetBuffer(FX_STRSIZE len); - void ReleaseBuffer(FX_STRSIZE len); - - int GetInteger() const; - float GetFloat() const; - - pdfium::Optional Find(const CFX_WideStringC& pSub, - FX_STRSIZE start = 0) const; - pdfium::Optional Find(wchar_t ch, FX_STRSIZE start = 0) const; - - bool Contains(const CFX_WideStringC& lpszSub, FX_STRSIZE start = 0) const { - return Find(lpszSub, start).has_value(); - } - - bool Contains(char ch, FX_STRSIZE start = 0) const { - return Find(ch, start).has_value(); - } - - FX_STRSIZE Replace(const CFX_WideStringC& pOld, const CFX_WideStringC& pNew); - FX_STRSIZE Remove(wchar_t ch); - - CFX_ByteString UTF8Encode() const; - CFX_ByteString UTF16LE_Encode() const; - - protected: - using StringData = CFX_StringDataTemplate; - - void ReallocBeforeWrite(FX_STRSIZE nLen); - void AllocBeforeWrite(FX_STRSIZE nLen); - void AllocCopy(CFX_WideString& dest, - FX_STRSIZE nCopyLen, - FX_STRSIZE nCopyIndex) const; - void AssignCopy(const wchar_t* pSrcData, FX_STRSIZE nSrcLen); - void Concat(const wchar_t* lpszSrcData, FX_STRSIZE nSrcLen); - - // Returns true unless we ran out of space. - bool TryVSWPrintf(FX_STRSIZE size, const wchar_t* format, va_list argList); - - CFX_RetainPtr m_pData; - - friend class fxcrt_WideStringConcatInPlace_Test; - friend class fxcrt_WideStringPool_Test; -}; - -inline CFX_WideString operator+(const CFX_WideStringC& str1, - const CFX_WideStringC& str2) { - return CFX_WideString(str1, str2); -} -inline CFX_WideString operator+(const CFX_WideStringC& str1, - const wchar_t* str2) { - return CFX_WideString(str1, str2); -} -inline CFX_WideString operator+(const wchar_t* str1, - const CFX_WideStringC& str2) { - return CFX_WideString(str1, str2); -} -inline CFX_WideString operator+(const CFX_WideStringC& str1, wchar_t ch) { - return CFX_WideString(str1, CFX_WideStringC(ch)); -} -inline CFX_WideString operator+(wchar_t ch, const CFX_WideStringC& str2) { - return CFX_WideString(ch, str2); -} -inline CFX_WideString operator+(const CFX_WideString& str1, - const CFX_WideString& str2) { - return CFX_WideString(str1.AsStringC(), str2.AsStringC()); -} -inline CFX_WideString operator+(const CFX_WideString& str1, wchar_t ch) { - return CFX_WideString(str1.AsStringC(), CFX_WideStringC(ch)); -} -inline CFX_WideString operator+(wchar_t ch, const CFX_WideString& str2) { - return CFX_WideString(ch, str2.AsStringC()); -} -inline CFX_WideString operator+(const CFX_WideString& str1, - const wchar_t* str2) { - return CFX_WideString(str1.AsStringC(), str2); -} -inline CFX_WideString operator+(const wchar_t* str1, - const CFX_WideString& str2) { - return CFX_WideString(str1, str2.AsStringC()); -} -inline CFX_WideString operator+(const CFX_WideString& str1, - const CFX_WideStringC& str2) { - return CFX_WideString(str1.AsStringC(), str2); -} -inline CFX_WideString operator+(const CFX_WideStringC& str1, - const CFX_WideString& str2) { - return CFX_WideString(str1, str2.AsStringC()); -} -inline bool operator==(const wchar_t* lhs, const CFX_WideString& rhs) { - return rhs == lhs; -} -inline bool operator==(const CFX_WideStringC& lhs, const CFX_WideString& rhs) { - return rhs == lhs; -} -inline bool operator!=(const wchar_t* lhs, const CFX_WideString& rhs) { - return rhs != lhs; -} -inline bool operator!=(const CFX_WideStringC& lhs, const CFX_WideString& rhs) { - return rhs != lhs; -} - -uint32_t FX_HashCode_GetW(const CFX_WideStringC& str, bool bIgnoreCase); - -std::wostream& operator<<(std::wostream& os, const CFX_WideString& str); -std::ostream& operator<<(std::ostream& os, const CFX_WideString& str); -std::wostream& operator<<(std::wostream& os, const CFX_WideStringC& str); -std::ostream& operator<<(std::ostream& os, const CFX_WideStringC& str); - -namespace std { - -template <> -struct hash { - std::size_t operator()(const CFX_WideString& str) const { - return FX_HashCode_GetW(str.AsStringC(), false); - } -}; - -} // namespace std - -extern template struct std::hash; - -#endif // CORE_FXCRT_CFX_WIDESTRING_H_ diff --git a/core/fxcrt/cfx_widestring_unittest.cpp b/core/fxcrt/cfx_widestring_unittest.cpp deleted file mode 100644 index 6f3bc0837f..0000000000 --- a/core/fxcrt/cfx_widestring_unittest.cpp +++ /dev/null @@ -1,1605 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "core/fxcrt/cfx_widestring.h" -#include "core/fxcrt/fx_string.h" - -#include -#include - -#include "testing/gtest/include/gtest/gtest.h" - -TEST(fxcrt, WideStringElementAccess) { - const CFX_WideString abc(L"abc"); - EXPECT_EQ(L'a', abc[0]); - EXPECT_EQ(L'b', abc[1]); - EXPECT_EQ(L'c', abc[2]); -#ifndef NDEBUG - EXPECT_DEATH({ abc[4]; }, ".*"); -#endif - - CFX_WideString mutable_abc = abc; - EXPECT_EQ(abc.c_str(), mutable_abc.c_str()); - EXPECT_EQ(L'a', mutable_abc[0]); - EXPECT_EQ(L'b', mutable_abc[1]); - EXPECT_EQ(L'c', mutable_abc[2]); - EXPECT_EQ(abc.c_str(), mutable_abc.c_str()); - EXPECT_EQ(L"abc", abc); - - const wchar_t* c_str = abc.c_str(); - mutable_abc.SetAt(0, L'd'); - EXPECT_EQ(c_str, abc.c_str()); - EXPECT_NE(c_str, mutable_abc.c_str()); - EXPECT_EQ(L"abc", abc); - EXPECT_EQ(L"dbc", mutable_abc); - - mutable_abc.SetAt(1, L'e'); - EXPECT_EQ(L"abc", abc); - EXPECT_EQ(L"dec", mutable_abc); - - mutable_abc.SetAt(2, L'f'); - EXPECT_EQ(L"abc", abc); - EXPECT_EQ(L"def", mutable_abc); -#ifndef NDEBUG - EXPECT_DEATH({ mutable_abc.SetAt(3, L'g'); }, ".*"); - EXPECT_EQ(L"abc", abc); -#endif -} - -TEST(fxcrt, WideStringOperatorLT) { - CFX_WideString empty; - CFX_WideString a(L"a"); - CFX_WideString abc(L"\x0110qq"); // Comes before despite endianness. - CFX_WideString def(L"\x1001qq"); // Comes after despite endianness. - - EXPECT_FALSE(empty < empty); - EXPECT_FALSE(a < a); - EXPECT_FALSE(abc < abc); - EXPECT_FALSE(def < def); - - EXPECT_TRUE(empty < a); - EXPECT_FALSE(a < empty); - - EXPECT_TRUE(empty < abc); - EXPECT_FALSE(abc < empty); - - EXPECT_TRUE(empty < def); - EXPECT_FALSE(def < empty); - - EXPECT_TRUE(a < abc); - EXPECT_FALSE(abc < a); - - EXPECT_TRUE(a < def); - EXPECT_FALSE(def < a); - - EXPECT_TRUE(abc < def); - EXPECT_FALSE(def < abc); -} - -TEST(fxcrt, WideStringOperatorEQ) { - CFX_WideString null_string; - EXPECT_TRUE(null_string == null_string); - - CFX_WideString empty_string(L""); - EXPECT_TRUE(empty_string == empty_string); - EXPECT_TRUE(empty_string == null_string); - EXPECT_TRUE(null_string == empty_string); - - CFX_WideString deleted_string(L"hello"); - deleted_string.Delete(0, 5); - EXPECT_TRUE(deleted_string == deleted_string); - EXPECT_TRUE(deleted_string == null_string); - EXPECT_TRUE(deleted_string == empty_string); - EXPECT_TRUE(null_string == deleted_string); - EXPECT_TRUE(null_string == empty_string); - - CFX_WideString wide_string(L"hello"); - EXPECT_TRUE(wide_string == wide_string); - EXPECT_FALSE(wide_string == null_string); - EXPECT_FALSE(wide_string == empty_string); - EXPECT_FALSE(wide_string == deleted_string); - EXPECT_FALSE(null_string == wide_string); - EXPECT_FALSE(empty_string == wide_string); - EXPECT_FALSE(deleted_string == wide_string); - - CFX_WideString wide_string_same1(L"hello"); - EXPECT_TRUE(wide_string == wide_string_same1); - EXPECT_TRUE(wide_string_same1 == wide_string); - - CFX_WideString wide_string_same2(wide_string); - EXPECT_TRUE(wide_string == wide_string_same2); - EXPECT_TRUE(wide_string_same2 == wide_string); - - CFX_WideString wide_string1(L"he"); - CFX_WideString wide_string2(L"hellp"); - CFX_WideString wide_string3(L"hellod"); - EXPECT_FALSE(wide_string == wide_string1); - EXPECT_FALSE(wide_string == wide_string2); - EXPECT_FALSE(wide_string == wide_string3); - EXPECT_FALSE(wide_string1 == wide_string); - EXPECT_FALSE(wide_string2 == wide_string); - EXPECT_FALSE(wide_string3 == wide_string); - - CFX_WideStringC null_string_c; - CFX_WideStringC empty_string_c(L""); - EXPECT_TRUE(null_string == null_string_c); - EXPECT_TRUE(null_string == empty_string_c); - EXPECT_TRUE(empty_string == null_string_c); - EXPECT_TRUE(empty_string == empty_string_c); - EXPECT_TRUE(deleted_string == null_string_c); - EXPECT_TRUE(deleted_string == empty_string_c); - EXPECT_TRUE(null_string_c == null_string); - EXPECT_TRUE(empty_string_c == null_string); - EXPECT_TRUE(null_string_c == empty_string); - EXPECT_TRUE(empty_string_c == empty_string); - EXPECT_TRUE(null_string_c == deleted_string); - EXPECT_TRUE(empty_string_c == deleted_string); - - CFX_WideStringC wide_string_c_same1(L"hello"); - EXPECT_TRUE(wide_string == wide_string_c_same1); - EXPECT_TRUE(wide_string_c_same1 == wide_string); - - CFX_WideStringC wide_string_c1(L"he"); - CFX_WideStringC wide_string_c2(L"hellp"); - CFX_WideStringC wide_string_c3(L"hellod"); - EXPECT_FALSE(wide_string == wide_string_c1); - EXPECT_FALSE(wide_string == wide_string_c2); - EXPECT_FALSE(wide_string == wide_string_c3); - EXPECT_FALSE(wide_string_c1 == wide_string); - EXPECT_FALSE(wide_string_c2 == wide_string); - EXPECT_FALSE(wide_string_c3 == wide_string); - - const wchar_t* c_null_string = nullptr; - const wchar_t* c_empty_string = L""; - EXPECT_TRUE(null_string == c_null_string); - EXPECT_TRUE(null_string == c_empty_string); - EXPECT_TRUE(empty_string == c_null_string); - EXPECT_TRUE(empty_string == c_empty_string); - EXPECT_TRUE(deleted_string == c_null_string); - EXPECT_TRUE(deleted_string == c_empty_string); - EXPECT_TRUE(c_null_string == null_string); - EXPECT_TRUE(c_empty_string == null_string); - EXPECT_TRUE(c_null_string == empty_string); - EXPECT_TRUE(c_empty_string == empty_string); - EXPECT_TRUE(c_null_string == deleted_string); - EXPECT_TRUE(c_empty_string == deleted_string); - - const wchar_t* c_string_same1 = L"hello"; - EXPECT_TRUE(wide_string == c_string_same1); - EXPECT_TRUE(c_string_same1 == wide_string); - - const wchar_t* c_string1 = L"he"; - const wchar_t* c_string2 = L"hellp"; - const wchar_t* c_string3 = L"hellod"; - EXPECT_FALSE(wide_string == c_string1); - EXPECT_FALSE(wide_string == c_string2); - EXPECT_FALSE(wide_string == c_string3); - EXPECT_FALSE(c_string1 == wide_string); - EXPECT_FALSE(c_string2 == wide_string); - EXPECT_FALSE(c_string3 == wide_string); -} - -TEST(fxcrt, WideStringOperatorNE) { - CFX_WideString null_string; - EXPECT_FALSE(null_string != null_string); - - CFX_WideString empty_string(L""); - EXPECT_FALSE(empty_string != empty_string); - EXPECT_FALSE(empty_string != null_string); - EXPECT_FALSE(null_string != empty_string); - - CFX_WideString deleted_string(L"hello"); - deleted_string.Delete(0, 5); - EXPECT_FALSE(deleted_string != deleted_string); - EXPECT_FALSE(deleted_string != null_string); - EXPECT_FALSE(deleted_string != empty_string); - EXPECT_FALSE(null_string != deleted_string); - EXPECT_FALSE(null_string != empty_string); - - CFX_WideString wide_string(L"hello"); - EXPECT_FALSE(wide_string != wide_string); - EXPECT_TRUE(wide_string != null_string); - EXPECT_TRUE(wide_string != empty_string); - EXPECT_TRUE(wide_string != deleted_string); - EXPECT_TRUE(null_string != wide_string); - EXPECT_TRUE(empty_string != wide_string); - EXPECT_TRUE(deleted_string != wide_string); - - CFX_WideString wide_string_same1(L"hello"); - EXPECT_FALSE(wide_string != wide_string_same1); - EXPECT_FALSE(wide_string_same1 != wide_string); - - CFX_WideString wide_string_same2(wide_string); - EXPECT_FALSE(wide_string != wide_string_same2); - EXPECT_FALSE(wide_string_same2 != wide_string); - - CFX_WideString wide_string1(L"he"); - CFX_WideString wide_string2(L"hellp"); - CFX_WideString wide_string3(L"hellod"); - EXPECT_TRUE(wide_string != wide_string1); - EXPECT_TRUE(wide_string != wide_string2); - EXPECT_TRUE(wide_string != wide_string3); - EXPECT_TRUE(wide_string1 != wide_string); - EXPECT_TRUE(wide_string2 != wide_string); - EXPECT_TRUE(wide_string3 != wide_string); - - CFX_WideStringC null_string_c; - CFX_WideStringC empty_string_c(L""); - EXPECT_FALSE(null_string != null_string_c); - EXPECT_FALSE(null_string != empty_string_c); - EXPECT_FALSE(empty_string != null_string_c); - EXPECT_FALSE(empty_string != empty_string_c); - EXPECT_FALSE(deleted_string != null_string_c); - EXPECT_FALSE(deleted_string != empty_string_c); - EXPECT_FALSE(null_string_c != null_string); - EXPECT_FALSE(empty_string_c != null_string); - EXPECT_FALSE(null_string_c != empty_string); - EXPECT_FALSE(empty_string_c != empty_string); - - CFX_WideStringC wide_string_c_same1(L"hello"); - EXPECT_FALSE(wide_string != wide_string_c_same1); - EXPECT_FALSE(wide_string_c_same1 != wide_string); - - CFX_WideStringC wide_string_c1(L"he"); - CFX_WideStringC wide_string_c2(L"hellp"); - CFX_WideStringC wide_string_c3(L"hellod"); - EXPECT_TRUE(wide_string != wide_string_c1); - EXPECT_TRUE(wide_string != wide_string_c2); - EXPECT_TRUE(wide_string != wide_string_c3); - EXPECT_TRUE(wide_string_c1 != wide_string); - EXPECT_TRUE(wide_string_c2 != wide_string); - EXPECT_TRUE(wide_string_c3 != wide_string); - - const wchar_t* c_null_string = nullptr; - const wchar_t* c_empty_string = L""; - EXPECT_FALSE(null_string != c_null_string); - EXPECT_FALSE(null_string != c_empty_string); - EXPECT_FALSE(empty_string != c_null_string); - EXPECT_FALSE(empty_string != c_empty_string); - EXPECT_FALSE(deleted_string != c_null_string); - EXPECT_FALSE(deleted_string != c_empty_string); - EXPECT_FALSE(c_null_string != null_string); - EXPECT_FALSE(c_empty_string != null_string); - EXPECT_FALSE(c_null_string != empty_string); - EXPECT_FALSE(c_empty_string != empty_string); - EXPECT_FALSE(c_null_string != deleted_string); - EXPECT_FALSE(c_empty_string != deleted_string); - - const wchar_t* c_string_same1 = L"hello"; - EXPECT_FALSE(wide_string != c_string_same1); - EXPECT_FALSE(c_string_same1 != wide_string); - - const wchar_t* c_string1 = L"he"; - const wchar_t* c_string2 = L"hellp"; - const wchar_t* c_string3 = L"hellod"; - EXPECT_TRUE(wide_string != c_string1); - EXPECT_TRUE(wide_string != c_string2); - EXPECT_TRUE(wide_string != c_string3); - EXPECT_TRUE(c_string1 != wide_string); - EXPECT_TRUE(c_string2 != wide_string); - EXPECT_TRUE(c_string3 != wide_string); -} - -TEST(fxcrt, WideStringConcatInPlace) { - CFX_WideString fred; - fred.Concat(L"FRED", 4); - EXPECT_EQ(L"FRED", fred); - - fred.Concat(L"DY", 2); - EXPECT_EQ(L"FREDDY", fred); - - fred.Delete(3, 3); - EXPECT_EQ(L"FRE", fred); - - fred.Concat(L"D", 1); - EXPECT_EQ(L"FRED", fred); - - CFX_WideString copy = fred; - fred.Concat(L"DY", 2); - EXPECT_EQ(L"FREDDY", fred); - EXPECT_EQ(L"FRED", copy); -} - -TEST(fxcrt, WideStringRemove) { - CFX_WideString freed(L"FREED"); - freed.Remove(L'E'); - EXPECT_EQ(L"FRD", freed); - freed.Remove(L'F'); - EXPECT_EQ(L"RD", freed); - freed.Remove(L'D'); - EXPECT_EQ(L"R", freed); - freed.Remove(L'X'); - EXPECT_EQ(L"R", freed); - freed.Remove(L'R'); - EXPECT_EQ(L"", freed); - - CFX_WideString empty; - empty.Remove(L'X'); - EXPECT_EQ(L"", empty); -} - -TEST(fxcrt, WideStringRemoveCopies) { - CFX_WideString freed(L"FREED"); - const wchar_t* old_buffer = freed.c_str(); - - // No change with single reference - no copy. - freed.Remove(L'Q'); - EXPECT_EQ(L"FREED", freed); - EXPECT_EQ(old_buffer, freed.c_str()); - - // Change with single reference - no copy. - freed.Remove(L'E'); - EXPECT_EQ(L"FRD", freed); - EXPECT_EQ(old_buffer, freed.c_str()); - - // No change with multiple references - no copy. - CFX_WideString shared(freed); - freed.Remove(L'Q'); - EXPECT_EQ(L"FRD", freed); - EXPECT_EQ(old_buffer, freed.c_str()); - EXPECT_EQ(old_buffer, shared.c_str()); - - // Change with multiple references -- must copy. - freed.Remove(L'D'); - EXPECT_EQ(L"FR", freed); - EXPECT_NE(old_buffer, freed.c_str()); - EXPECT_EQ(L"FRD", shared); - EXPECT_EQ(old_buffer, shared.c_str()); -} - -TEST(fxcrt, WideStringReplace) { - CFX_WideString fred(L"FRED"); - fred.Replace(L"FR", L"BL"); - EXPECT_EQ(L"BLED", fred); - fred.Replace(L"D", L"DDY"); - EXPECT_EQ(L"BLEDDY", fred); - fred.Replace(L"LEDD", L""); - EXPECT_EQ(L"BY", fred); - fred.Replace(L"X", L"CLAMS"); - EXPECT_EQ(L"BY", fred); - fred.Replace(L"BY", L"HI"); - EXPECT_EQ(L"HI", fred); - fred.Replace(L"", L"CLAMS"); - EXPECT_EQ(L"HI", fred); - fred.Replace(L"HI", L""); - EXPECT_EQ(L"", fred); -} - -TEST(fxcrt, WideStringInsert) { - CFX_WideString fred(L"FRED"); - EXPECT_EQ(5u, fred.Insert(0, 'S')); - EXPECT_EQ(L"SFRED", fred); - EXPECT_EQ(6u, fred.Insert(1, 'T')); - EXPECT_EQ(L"STFRED", fred); - EXPECT_EQ(7u, fred.Insert(4, 'U')); - EXPECT_EQ(L"STFRUED", fred); - EXPECT_EQ(8u, fred.Insert(7, 'V')); - EXPECT_EQ(L"STFRUEDV", fred); - EXPECT_EQ(8u, fred.Insert(12, 'P')); - EXPECT_EQ(L"STFRUEDV", fred); - { - CFX_WideString empty; - EXPECT_EQ(1u, empty.Insert(0, 'X')); - EXPECT_EQ(L"X", empty); - } - { - CFX_WideString empty; - EXPECT_EQ(0u, empty.Insert(5, 'X')); - EXPECT_NE(L"X", empty); - } -} - -TEST(fxcrt, WideStringInsertAtFrontAndInsertAtBack) { - { - CFX_WideString empty; - EXPECT_EQ(1u, empty.InsertAtFront('D')); - EXPECT_EQ(L"D", empty); - EXPECT_EQ(2u, empty.InsertAtFront('E')); - EXPECT_EQ(L"ED", empty); - EXPECT_EQ(3u, empty.InsertAtFront('R')); - EXPECT_EQ(L"RED", empty); - EXPECT_EQ(4u, empty.InsertAtFront('F')); - EXPECT_EQ(L"FRED", empty); - } - { - CFX_WideString empty; - EXPECT_EQ(1u, empty.InsertAtBack('F')); - EXPECT_EQ(L"F", empty); - EXPECT_EQ(2u, empty.InsertAtBack('R')); - EXPECT_EQ(L"FR", empty); - EXPECT_EQ(3u, empty.InsertAtBack('E')); - EXPECT_EQ(L"FRE", empty); - EXPECT_EQ(4u, empty.InsertAtBack('D')); - EXPECT_EQ(L"FRED", empty); - } - { - CFX_WideString empty; - EXPECT_EQ(1u, empty.InsertAtBack('E')); - EXPECT_EQ(L"E", empty); - EXPECT_EQ(2u, empty.InsertAtFront('R')); - EXPECT_EQ(L"RE", empty); - EXPECT_EQ(3u, empty.InsertAtBack('D')); - EXPECT_EQ(L"RED", empty); - EXPECT_EQ(4u, empty.InsertAtFront('F')); - EXPECT_EQ(L"FRED", empty); - } -} - -TEST(fxcrt, WideStringDelete) { - CFX_WideString fred(L"FRED"); - EXPECT_EQ(4u, fred.Delete(0, 0)); - EXPECT_EQ(L"FRED", fred); - EXPECT_EQ(2u, fred.Delete(0, 2)); - EXPECT_EQ(L"ED", fred); - EXPECT_EQ(1u, fred.Delete(1)); - EXPECT_EQ(L"E", fred); - EXPECT_EQ(0u, fred.Delete(0)); - EXPECT_EQ(L"", fred); - EXPECT_EQ(0u, fred.Delete(0)); - EXPECT_EQ(L"", fred); - - CFX_WideString empty; - EXPECT_EQ(0u, empty.Delete(0)); - EXPECT_EQ(L"", empty); - EXPECT_EQ(0u, empty.Delete(1)); - EXPECT_EQ(L"", empty); -} - -TEST(fxcrt, WideStringMid) { - CFX_WideString fred(L"FRED"); - EXPECT_EQ(L"", fred.Mid(0, 0)); - EXPECT_EQ(L"", fred.Mid(3, 0)); - EXPECT_EQ(L"FRED", fred.Mid(0, 4)); - EXPECT_EQ(L"RED", fred.Mid(1, 3)); - EXPECT_EQ(L"ED", fred.Mid(2, 2)); - EXPECT_EQ(L"D", fred.Mid(3, 1)); - EXPECT_EQ(L"F", fred.Mid(0, 1)); - EXPECT_EQ(L"R", fred.Mid(1, 1)); - EXPECT_EQ(L"E", fred.Mid(2, 1)); - EXPECT_EQ(L"D", fred.Mid(3, 1)); - EXPECT_EQ(L"FR", fred.Mid(0, 2)); - EXPECT_EQ(L"FRED", fred.Mid(0, 4)); - EXPECT_EQ(L"", fred.Mid(0, 10)); - - EXPECT_EQ(L"", fred.Mid(1, 4)); - EXPECT_EQ(L"", fred.Mid(4, 1)); - - CFX_WideString empty; - EXPECT_EQ(L"", empty.Mid(0, 0)); -} - -TEST(fxcrt, WideStringLeft) { - CFX_WideString fred(L"FRED"); - EXPECT_EQ(L"", fred.Left(0)); - EXPECT_EQ(L"F", fred.Left(1)); - EXPECT_EQ(L"FR", fred.Left(2)); - EXPECT_EQ(L"FRE", fred.Left(3)); - EXPECT_EQ(L"FRED", fred.Left(4)); - - EXPECT_EQ(L"", fred.Left(5)); - - CFX_WideString empty; - EXPECT_EQ(L"", empty.Left(0)); - EXPECT_EQ(L"", empty.Left(1)); -} - -TEST(fxcrt, WideStringRight) { - CFX_WideString fred(L"FRED"); - EXPECT_EQ(L"", fred.Right(0)); - EXPECT_EQ(L"D", fred.Right(1)); - EXPECT_EQ(L"ED", fred.Right(2)); - EXPECT_EQ(L"RED", fred.Right(3)); - EXPECT_EQ(L"FRED", fred.Right(4)); - - EXPECT_EQ(L"", fred.Right(5)); - - CFX_WideString empty; - EXPECT_EQ(L"", empty.Right(0)); - EXPECT_EQ(L"", empty.Right(1)); -} - -TEST(fxcrt, WideStringFind) { - CFX_WideString null_string; - EXPECT_FALSE(null_string.Find(L'a').has_value()); - EXPECT_FALSE(null_string.Find(L'\0').has_value()); - - CFX_WideString empty_string(L""); - EXPECT_FALSE(empty_string.Find(L'a').has_value()); - EXPECT_FALSE(empty_string.Find(L'\0').has_value()); - - pdfium::Optional result; - CFX_WideString single_string(L"a"); - result = single_string.Find(L'a'); - ASSERT_TRUE(result.has_value()); - EXPECT_EQ(0u, result.value()); - EXPECT_FALSE(single_string.Find(L'b').has_value()); - EXPECT_FALSE(single_string.Find(L'\0').has_value()); - - CFX_WideString longer_string(L"abccc"); - result = longer_string.Find(L'a'); - ASSERT_TRUE(result.has_value()); - EXPECT_EQ(0u, result.value()); - result = longer_string.Find(L'c'); - ASSERT_TRUE(result.has_value()); - EXPECT_EQ(2u, result.value()); - result = longer_string.Find(L'c', 3); - ASSERT_TRUE(result.has_value()); - EXPECT_EQ(3u, result.value()); - EXPECT_FALSE(longer_string.Find(L'\0').has_value()); - - result = longer_string.Find(L"ab"); - ASSERT_TRUE(result.has_value()); - EXPECT_EQ(0u, result.value()); - result = longer_string.Find(L"ccc"); - ASSERT_TRUE(result.has_value()); - EXPECT_EQ(2u, result.value()); - result = longer_string.Find(L"cc", 3); - ASSERT_TRUE(result.has_value()); - EXPECT_EQ(3u, result.value()); - EXPECT_FALSE(longer_string.Find(L"d").has_value()); - - CFX_WideString hibyte_string( - L"ab\xff8c" - L"def"); - result = hibyte_string.Find(L'\xff8c'); - ASSERT_TRUE(result.has_value()); - EXPECT_EQ(2u, result.value()); -} - -TEST(fxcrt, WideStringUpperLower) { - CFX_WideString fred(L"F-Re.42D"); - fred.MakeLower(); - EXPECT_EQ(L"f-re.42d", fred); - fred.MakeUpper(); - EXPECT_EQ(L"F-RE.42D", fred); - - CFX_WideString empty; - empty.MakeLower(); - EXPECT_EQ(L"", empty); - empty.MakeUpper(); - EXPECT_EQ(L"", empty); -} - -TEST(fxcrt, WideStringTrimRight) { - CFX_WideString fred(L" FRED "); - fred.TrimRight(); - EXPECT_EQ(L" FRED", fred); - fred.TrimRight(L'E'); - EXPECT_EQ(L" FRED", fred); - fred.TrimRight(L'D'); - EXPECT_EQ(L" FRE", fred); - fred.TrimRight(L"ERP"); - EXPECT_EQ(L" F", fred); - - CFX_WideString blank(L" "); - blank.TrimRight(L"ERP"); - EXPECT_EQ(L" ", blank); - blank.TrimRight(L'E'); - EXPECT_EQ(L" ", blank); - blank.TrimRight(); - EXPECT_EQ(L"", blank); - - CFX_WideString empty; - empty.TrimRight(L"ERP"); - EXPECT_EQ(L"", empty); - empty.TrimRight(L'E'); - EXPECT_EQ(L"", empty); - empty.TrimRight(); - EXPECT_EQ(L"", empty); -} - -TEST(fxcrt, WideStringTrimRightCopies) { - { - // With a single reference, no copy takes place. - CFX_WideString fred(L" FRED "); - const wchar_t* old_buffer = fred.c_str(); - fred.TrimRight(); - EXPECT_EQ(L" FRED", fred); - EXPECT_EQ(old_buffer, fred.c_str()); - } - { - // With multiple references, we must copy. - CFX_WideString fred(L" FRED "); - CFX_WideString other_fred = fred; - const wchar_t* old_buffer = fred.c_str(); - fred.TrimRight(); - EXPECT_EQ(L" FRED", fred); - EXPECT_EQ(L" FRED ", other_fred); - EXPECT_NE(old_buffer, fred.c_str()); - } - { - // With multiple references, but no modifications, no copy. - CFX_WideString fred(L"FRED"); - CFX_WideString other_fred = fred; - const wchar_t* old_buffer = fred.c_str(); - fred.TrimRight(); - EXPECT_EQ(L"FRED", fred); - EXPECT_EQ(L"FRED", other_fred); - EXPECT_EQ(old_buffer, fred.c_str()); - } -} - -TEST(fxcrt, WideStringTrimLeft) { - CFX_WideString fred(L" FRED "); - fred.TrimLeft(); - EXPECT_EQ(L"FRED ", fred); - fred.TrimLeft(L'E'); - EXPECT_EQ(L"FRED ", fred); - fred.TrimLeft(L'F'); - EXPECT_EQ(L"RED ", fred); - fred.TrimLeft(L"ERP"); - EXPECT_EQ(L"D ", fred); - - CFX_WideString blank(L" "); - blank.TrimLeft(L"ERP"); - EXPECT_EQ(L" ", blank); - blank.TrimLeft(L'E'); - EXPECT_EQ(L" ", blank); - blank.TrimLeft(); - EXPECT_EQ(L"", blank); - - CFX_WideString empty; - empty.TrimLeft(L"ERP"); - EXPECT_EQ(L"", empty); - empty.TrimLeft(L'E'); - EXPECT_EQ(L"", empty); - empty.TrimLeft(); - EXPECT_EQ(L"", empty); -} - -TEST(fxcrt, WideStringTrimLeftCopies) { - { - // With a single reference, no copy takes place. - CFX_WideString fred(L" FRED "); - const wchar_t* old_buffer = fred.c_str(); - fred.TrimLeft(); - EXPECT_EQ(L"FRED ", fred); - EXPECT_EQ(old_buffer, fred.c_str()); - } - { - // With multiple references, we must copy. - CFX_WideString fred(L" FRED "); - CFX_WideString other_fred = fred; - const wchar_t* old_buffer = fred.c_str(); - fred.TrimLeft(); - EXPECT_EQ(L"FRED ", fred); - EXPECT_EQ(L" FRED ", other_fred); - EXPECT_NE(old_buffer, fred.c_str()); - } - { - // With multiple references, but no modifications, no copy. - CFX_WideString fred(L"FRED"); - CFX_WideString other_fred = fred; - const wchar_t* old_buffer = fred.c_str(); - fred.TrimLeft(); - EXPECT_EQ(L"FRED", fred); - EXPECT_EQ(L"FRED", other_fred); - EXPECT_EQ(old_buffer, fred.c_str()); - } -} - -TEST(fxcrt, WideStringReserve) { - { - CFX_WideString str; - str.Reserve(6); - const wchar_t* old_buffer = str.c_str(); - str += L"ABCDEF"; - EXPECT_EQ(old_buffer, str.c_str()); - str += L"Blah Blah Blah Blah Blah Blah"; - EXPECT_NE(old_buffer, str.c_str()); - } - { - CFX_WideString str(L"A"); - str.Reserve(6); - const wchar_t* old_buffer = str.c_str(); - str += L"BCDEF"; - EXPECT_EQ(old_buffer, str.c_str()); - str += L"Blah Blah Blah Blah Blah Blah"; - EXPECT_NE(old_buffer, str.c_str()); - } -} - -TEST(fxcrt, WideStringGetBuffer) { - { - CFX_WideString str; - wchar_t* buffer = str.GetBuffer(12); - wcscpy(buffer, L"clams"); - str.ReleaseBuffer(str.GetStringLength()); - EXPECT_EQ(L"clams", str); - } - { - CFX_WideString str(L"cl"); - wchar_t* buffer = str.GetBuffer(12); - wcscpy(buffer + 2, L"ams"); - str.ReleaseBuffer(str.GetStringLength()); - EXPECT_EQ(L"clams", str); - } -} - -TEST(fxcrt, WideStringReleaseBuffer) { - { - CFX_WideString str; - str.Reserve(12); - str += L"clams"; - const wchar_t* old_buffer = str.c_str(); - str.ReleaseBuffer(4); - EXPECT_EQ(old_buffer, str.c_str()); - EXPECT_EQ(L"clam", str); - } - { - CFX_WideString str(L"c"); - str.Reserve(12); - str += L"lams"; - const wchar_t* old_buffer = str.c_str(); - str.ReleaseBuffer(4); - EXPECT_EQ(old_buffer, str.c_str()); - EXPECT_EQ(L"clam", str); - } - { - CFX_WideString str; - str.Reserve(200); - str += L"clams"; - const wchar_t* old_buffer = str.c_str(); - str.ReleaseBuffer(4); - EXPECT_NE(old_buffer, str.c_str()); - EXPECT_EQ(L"clam", str); - } - { - CFX_WideString str(L"c"); - str.Reserve(200); - str += L"lams"; - const wchar_t* old_buffer = str.c_str(); - str.ReleaseBuffer(4); - EXPECT_NE(old_buffer, str.c_str()); - EXPECT_EQ(L"clam", str); - } -} - -TEST(fxcrt, WideStringEmptyReverseIterator) { - CFX_WideString empty; - auto iter = empty.rbegin(); - EXPECT_TRUE(iter == empty.rend()); - EXPECT_FALSE(iter != empty.rend()); - EXPECT_FALSE(iter < empty.rend()); -} - -TEST(fxcrt, WideStringOneCharReverseIterator) { - CFX_WideString one_str(L"a"); - auto iter = one_str.rbegin(); - EXPECT_FALSE(iter == one_str.rend()); - EXPECT_TRUE(iter != one_str.rend()); - EXPECT_TRUE(iter < one_str.rend()); - - char ch = *iter++; - EXPECT_EQ('a', ch); - EXPECT_TRUE(iter == one_str.rend()); - EXPECT_FALSE(iter != one_str.rend()); - EXPECT_FALSE(iter < one_str.rend()); -} - -TEST(fxcrt, WideStringMultiCharReverseIterator) { - CFX_WideString multi_str(L"abcd"); - auto iter = multi_str.rbegin(); - EXPECT_FALSE(iter == multi_str.rend()); - - char ch = *iter++; - EXPECT_EQ('d', ch); - EXPECT_EQ('c', *iter); - EXPECT_FALSE(iter == multi_str.rend()); - - ch = *(++iter); - EXPECT_EQ('b', ch); - EXPECT_EQ('b', *iter); - EXPECT_FALSE(iter == multi_str.rend()); - - ch = *iter++; - EXPECT_EQ('b', ch); - EXPECT_EQ('a', *iter); - EXPECT_FALSE(iter == multi_str.rend()); - - ch = *iter++; - EXPECT_EQ('a', ch); - EXPECT_TRUE(iter == multi_str.rend()); - - ch = *(--iter); - EXPECT_EQ('a', ch); - EXPECT_EQ('a', *iter); - EXPECT_FALSE(iter == multi_str.rend()); - - ch = *iter--; - EXPECT_EQ('a', ch); - EXPECT_EQ('b', *iter); - EXPECT_FALSE(iter == multi_str.rend()); - - ch = *iter--; - EXPECT_EQ('b', ch); - EXPECT_EQ('c', *iter); - EXPECT_FALSE(iter == multi_str.rend()); - - ch = *(--iter); - EXPECT_EQ('d', ch); - EXPECT_EQ('d', *iter); - EXPECT_TRUE(iter == multi_str.rbegin()); -} - -TEST(fxcrt, WideStringUTF16LE_Encode) { - struct UTF16LEEncodeCase { - CFX_WideString ws; - CFX_ByteString bs; - } utf16le_encode_cases[] = { - {L"", CFX_ByteString("\0\0", 2)}, - {L"abc", CFX_ByteString("a\0b\0c\0\0\0", 8)}, - {L"abcdef", CFX_ByteString("a\0b\0c\0d\0e\0f\0\0\0", 14)}, - {L"abc\0def", CFX_ByteString("a\0b\0c\0\0\0", 8)}, - {L"\xaabb\xccdd", CFX_ByteString("\xbb\xaa\xdd\xcc\0\0", 6)}, - {L"\x3132\x6162", CFX_ByteString("\x32\x31\x62\x61\0\0", 6)}, - }; - - for (size_t i = 0; i < FX_ArraySize(utf16le_encode_cases); ++i) { - EXPECT_EQ(utf16le_encode_cases[i].bs, - utf16le_encode_cases[i].ws.UTF16LE_Encode()) - << " for case number " << i; - } -} - -TEST(fxcrt, WideStringCFromVector) { - std::vector null_vec; - CFX_WideStringC null_string(null_vec); - EXPECT_EQ(0u, null_string.GetLength()); - - std::vector lower_a_vec( - 10, static_cast(L'a')); - CFX_WideStringC lower_a_string(lower_a_vec); - EXPECT_EQ(10u, lower_a_string.GetLength()); - EXPECT_EQ(L"aaaaaaaaaa", lower_a_string); - - std::vector cleared_vec; - cleared_vec.push_back(42); - cleared_vec.pop_back(); - CFX_WideStringC cleared_string(cleared_vec); - EXPECT_EQ(0u, cleared_string.GetLength()); - EXPECT_EQ(nullptr, cleared_string.raw_str()); -} - -TEST(fxcrt, WideStringCElementAccess) { - CFX_WideStringC abc(L"abc"); - EXPECT_EQ(L'a', static_cast(abc[0])); - EXPECT_EQ(L'b', static_cast(abc[1])); - EXPECT_EQ(L'c', static_cast(abc[2])); -#ifndef NDEBUG - EXPECT_DEATH({ abc[4]; }, ".*"); -#endif -} - -TEST(fxcrt, WideStringCOperatorLT) { - CFX_WideStringC empty; - CFX_WideStringC a(L"a"); - CFX_WideStringC abc(L"\x0110qq"); // Comes InsertAtFront despite endianness. - CFX_WideStringC def(L"\x1001qq"); // Comes InsertAtBack despite endianness. - - EXPECT_FALSE(empty < empty); - EXPECT_FALSE(a < a); - EXPECT_FALSE(abc < abc); - EXPECT_FALSE(def < def); - - EXPECT_TRUE(empty < a); - EXPECT_FALSE(a < empty); - - EXPECT_TRUE(empty < abc); - EXPECT_FALSE(abc < empty); - - EXPECT_TRUE(empty < def); - EXPECT_FALSE(def < empty); - - EXPECT_TRUE(a < abc); - EXPECT_FALSE(abc < a); - - EXPECT_TRUE(a < def); - EXPECT_FALSE(def < a); - - EXPECT_TRUE(abc < def); - EXPECT_FALSE(def < abc); -} - -TEST(fxcrt, WideStringCOperatorEQ) { - CFX_WideStringC wide_string_c(L"hello"); - EXPECT_TRUE(wide_string_c == wide_string_c); - - CFX_WideStringC wide_string_c_same1(L"hello"); - EXPECT_TRUE(wide_string_c == wide_string_c_same1); - EXPECT_TRUE(wide_string_c_same1 == wide_string_c); - - CFX_WideStringC wide_string_c_same2(wide_string_c); - EXPECT_TRUE(wide_string_c == wide_string_c_same2); - EXPECT_TRUE(wide_string_c_same2 == wide_string_c); - - CFX_WideStringC wide_string_c1(L"he"); - CFX_WideStringC wide_string_c2(L"hellp"); - CFX_WideStringC wide_string_c3(L"hellod"); - EXPECT_FALSE(wide_string_c == wide_string_c1); - EXPECT_FALSE(wide_string_c == wide_string_c2); - EXPECT_FALSE(wide_string_c == wide_string_c3); - EXPECT_FALSE(wide_string_c1 == wide_string_c); - EXPECT_FALSE(wide_string_c2 == wide_string_c); - EXPECT_FALSE(wide_string_c3 == wide_string_c); - - CFX_WideString wide_string_same1(L"hello"); - EXPECT_TRUE(wide_string_c == wide_string_same1); - EXPECT_TRUE(wide_string_same1 == wide_string_c); - - CFX_WideString wide_string1(L"he"); - CFX_WideString wide_string2(L"hellp"); - CFX_WideString wide_string3(L"hellod"); - EXPECT_FALSE(wide_string_c == wide_string1); - EXPECT_FALSE(wide_string_c == wide_string2); - EXPECT_FALSE(wide_string_c == wide_string3); - EXPECT_FALSE(wide_string1 == wide_string_c); - EXPECT_FALSE(wide_string2 == wide_string_c); - EXPECT_FALSE(wide_string3 == wide_string_c); - - const wchar_t* c_string_same1 = L"hello"; - EXPECT_TRUE(wide_string_c == c_string_same1); - EXPECT_TRUE(c_string_same1 == wide_string_c); - - const wchar_t* c_string1 = L"he"; - const wchar_t* c_string2 = L"hellp"; - const wchar_t* c_string3 = L"hellod"; - EXPECT_FALSE(wide_string_c == c_string1); - EXPECT_FALSE(wide_string_c == c_string2); - EXPECT_FALSE(wide_string_c == c_string3); - - EXPECT_FALSE(c_string1 == wide_string_c); - EXPECT_FALSE(c_string2 == wide_string_c); - EXPECT_FALSE(c_string3 == wide_string_c); -} - -TEST(fxcrt, WideStringCOperatorNE) { - CFX_WideStringC wide_string_c(L"hello"); - EXPECT_FALSE(wide_string_c != wide_string_c); - - CFX_WideStringC wide_string_c_same1(L"hello"); - EXPECT_FALSE(wide_string_c != wide_string_c_same1); - EXPECT_FALSE(wide_string_c_same1 != wide_string_c); - - CFX_WideStringC wide_string_c_same2(wide_string_c); - EXPECT_FALSE(wide_string_c != wide_string_c_same2); - EXPECT_FALSE(wide_string_c_same2 != wide_string_c); - - CFX_WideStringC wide_string_c1(L"he"); - CFX_WideStringC wide_string_c2(L"hellp"); - CFX_WideStringC wide_string_c3(L"hellod"); - EXPECT_TRUE(wide_string_c != wide_string_c1); - EXPECT_TRUE(wide_string_c != wide_string_c2); - EXPECT_TRUE(wide_string_c != wide_string_c3); - EXPECT_TRUE(wide_string_c1 != wide_string_c); - EXPECT_TRUE(wide_string_c2 != wide_string_c); - EXPECT_TRUE(wide_string_c3 != wide_string_c); - - CFX_WideString wide_string_same1(L"hello"); - EXPECT_FALSE(wide_string_c != wide_string_same1); - EXPECT_FALSE(wide_string_same1 != wide_string_c); - - CFX_WideString wide_string1(L"he"); - CFX_WideString wide_string2(L"hellp"); - CFX_WideString wide_string3(L"hellod"); - EXPECT_TRUE(wide_string_c != wide_string1); - EXPECT_TRUE(wide_string_c != wide_string2); - EXPECT_TRUE(wide_string_c != wide_string3); - EXPECT_TRUE(wide_string1 != wide_string_c); - EXPECT_TRUE(wide_string2 != wide_string_c); - EXPECT_TRUE(wide_string3 != wide_string_c); - - const wchar_t* c_string_same1 = L"hello"; - EXPECT_FALSE(wide_string_c != c_string_same1); - EXPECT_FALSE(c_string_same1 != wide_string_c); - - const wchar_t* c_string1 = L"he"; - const wchar_t* c_string2 = L"hellp"; - const wchar_t* c_string3 = L"hellod"; - EXPECT_TRUE(wide_string_c != c_string1); - EXPECT_TRUE(wide_string_c != c_string2); - EXPECT_TRUE(wide_string_c != c_string3); - - EXPECT_TRUE(c_string1 != wide_string_c); - EXPECT_TRUE(c_string2 != wide_string_c); - EXPECT_TRUE(c_string3 != wide_string_c); -} - -TEST(fxcrt, WideStringCFind) { - CFX_WideStringC null_string; - EXPECT_FALSE(null_string.Find(L'a').has_value()); - EXPECT_FALSE(null_string.Find(L'\0').has_value()); - - CFX_WideStringC empty_string(L""); - EXPECT_FALSE(empty_string.Find(L'a').has_value()); - EXPECT_FALSE(empty_string.Find(L'\0').has_value()); - - pdfium::Optional result; - CFX_WideStringC single_string(L"a"); - result = single_string.Find(L'a'); - ASSERT_TRUE(result.has_value()); - EXPECT_EQ(0u, result.value()); - EXPECT_FALSE(single_string.Find(L'b').has_value()); - EXPECT_FALSE(single_string.Find(L'\0').has_value()); - - CFX_WideStringC longer_string(L"abccc"); - result = longer_string.Find(L'a'); - ASSERT_TRUE(result.has_value()); - EXPECT_EQ(0u, result.value()); - result = longer_string.Find(L'c'); - ASSERT_TRUE(result.has_value()); - EXPECT_EQ(2u, result.value()); - EXPECT_FALSE(longer_string.Find(L'd').has_value()); - EXPECT_FALSE(longer_string.Find(L'\0').has_value()); - - CFX_WideStringC hibyte_string( - L"ab\xFF8c" - L"def"); - result = hibyte_string.Find(L'\xFF8c'); - ASSERT_TRUE(result.has_value()); - EXPECT_EQ(2u, result.value()); -} - -TEST(fxcrt, WideStringCNullIterator) { - CFX_WideStringC null_str; - int32_t sum = 0; - bool any_present = false; - for (const auto& c : null_str) { - sum += c; // Avoid unused arg warnings. - any_present = true; - } - EXPECT_FALSE(any_present); - EXPECT_EQ(0, sum); -} - -TEST(fxcrt, WideStringCEmptyIterator) { - CFX_WideStringC empty_str(L""); - int32_t sum = 0; - bool any_present = false; - for (const auto& c : empty_str) { - any_present = true; - sum += c; // Avoid unused arg warnings. - } - EXPECT_FALSE(any_present); - EXPECT_EQ(0, sum); -} - -TEST(fxcrt, WideStringCOneCharIterator) { - CFX_WideStringC one_str(L"a"); - int32_t sum = 0; - bool any_present = false; - for (const auto& c : one_str) { - any_present = true; - sum += c; // Avoid unused arg warnings. - } - EXPECT_TRUE(any_present); - EXPECT_EQ(static_cast(L'a'), sum); -} - -TEST(fxcrt, WideStringCMultiCharIterator) { - CFX_WideStringC one_str(L"abc"); - int32_t sum = 0; - bool any_present = false; - for (const auto& c : one_str) { - any_present = true; - sum += c; // Avoid unused arg warnings. - } - EXPECT_TRUE(any_present); - EXPECT_EQ(static_cast(L'a' + L'b' + L'c'), sum); -} - -TEST(fxcrt, WideStringCEmptyReverseIterator) { - CFX_WideStringC empty; - auto iter = empty.rbegin(); - EXPECT_TRUE(iter == empty.rend()); - EXPECT_FALSE(iter != empty.rend()); - EXPECT_FALSE(iter < empty.rend()); -} - -TEST(fxcrt, WideStringCOneCharReverseIterator) { - CFX_WideStringC one_str(L"a"); - auto iter = one_str.rbegin(); - EXPECT_FALSE(iter == one_str.rend()); - EXPECT_TRUE(iter != one_str.rend()); - EXPECT_TRUE(iter < one_str.rend()); - - char ch = *iter++; - EXPECT_EQ('a', ch); - EXPECT_TRUE(iter == one_str.rend()); - EXPECT_FALSE(iter != one_str.rend()); - EXPECT_FALSE(iter < one_str.rend()); -} - -TEST(fxcrt, WideStringCMultiCharReverseIterator) { - CFX_WideStringC multi_str(L"abcd"); - auto iter = multi_str.rbegin(); - EXPECT_FALSE(iter == multi_str.rend()); - - char ch = *iter++; - EXPECT_EQ('d', ch); - EXPECT_EQ('c', *iter); - EXPECT_FALSE(iter == multi_str.rend()); - - ch = *(++iter); - EXPECT_EQ('b', ch); - EXPECT_EQ('b', *iter); - EXPECT_FALSE(iter == multi_str.rend()); - - ch = *iter++; - EXPECT_EQ('b', ch); - EXPECT_EQ('a', *iter); - EXPECT_FALSE(iter == multi_str.rend()); - - ch = *iter++; - EXPECT_EQ('a', ch); - EXPECT_TRUE(iter == multi_str.rend()); - - ch = *(--iter); - EXPECT_EQ('a', ch); - EXPECT_EQ('a', *iter); - EXPECT_FALSE(iter == multi_str.rend()); - - ch = *iter--; - EXPECT_EQ('a', ch); - EXPECT_EQ('b', *iter); - EXPECT_FALSE(iter == multi_str.rend()); - - ch = *iter--; - EXPECT_EQ('b', ch); - EXPECT_EQ('c', *iter); - EXPECT_FALSE(iter == multi_str.rend()); - - ch = *(--iter); - EXPECT_EQ('d', ch); - EXPECT_EQ('d', *iter); - EXPECT_TRUE(iter == multi_str.rbegin()); -} - -TEST(fxcrt, WideStringCAnyAllNoneOf) { - CFX_WideStringC str(L"aaaaaaaaaaaaaaaaab"); - EXPECT_FALSE(std::all_of(str.begin(), str.end(), - [](const wchar_t& c) { return c == L'a'; })); - - EXPECT_FALSE(std::none_of(str.begin(), str.end(), - [](const wchar_t& c) { return c == L'a'; })); - - EXPECT_TRUE(std::any_of(str.begin(), str.end(), - [](const wchar_t& c) { return c == L'a'; })); - - EXPECT_TRUE(pdfium::ContainsValue(str, L'a')); - EXPECT_TRUE(pdfium::ContainsValue(str, L'b')); - EXPECT_FALSE(pdfium::ContainsValue(str, L'z')); -} - -TEST(fxcrt, WideStringCTrimmedRight) { - CFX_WideStringC fred(L"FRED"); - EXPECT_EQ(L"FRED", fred.TrimmedRight(L'E')); - EXPECT_EQ(L"FRE", fred.TrimmedRight(L'D')); - CFX_WideStringC fredd(L"FREDD"); - EXPECT_EQ(L"FRE", fred.TrimmedRight(L'D')); -} - -TEST(fxcrt, WideStringFormatWidth) { - { - CFX_WideString str; - str.Format(L"%5d", 1); - EXPECT_EQ(L" 1", str); - } - - { - CFX_WideString str; - str.Format(L"%d", 1); - EXPECT_EQ(L"1", str); - } - - { - CFX_WideString str; - str.Format(L"%*d", 5, 1); - EXPECT_EQ(L" 1", str); - } - - { - CFX_WideString str; - str.Format(L"%-1d", 1); - EXPECT_EQ(L"1", str); - } - - { - CFX_WideString str; - str.Format(L"%0d", 1); - EXPECT_EQ(L"1", str); - } - - { - CFX_WideString str; - str.Format(L"%1048576d", 1); - EXPECT_EQ(L"", str); - } -} - -TEST(fxcrt, WideStringFormatPrecision) { - { - CFX_WideString str; - str.Format(L"%.2f", 1.12345); - EXPECT_EQ(L"1.12", str); - } - - { - CFX_WideString str; - str.Format(L"%.*f", 3, 1.12345); - EXPECT_EQ(L"1.123", str); - } - - { - CFX_WideString str; - str.Format(L"%f", 1.12345); - EXPECT_EQ(L"1.123450", str); - } - - { - CFX_WideString str; - str.Format(L"%-1f", 1.12345); - EXPECT_EQ(L"1.123450", str); - } - - { - CFX_WideString str; - str.Format(L"%0f", 1.12345); - EXPECT_EQ(L"1.123450", str); - } - - { - CFX_WideString str; - str.Format(L"%.1048576f", 1.2); - EXPECT_EQ(L"", str); - } -} - -TEST(fxcrt, WideStringFormatOutOfRangeChar) { - CFX_WideString str; - str.Format(L"unsupported char '%c'", 0x00FF00FF); -} - -TEST(fxcrt, EmptyWideString) { - CFX_WideString empty_str; - EXPECT_TRUE(empty_str.IsEmpty()); - EXPECT_EQ(0u, empty_str.GetLength()); - const wchar_t* cstr = empty_str.c_str(); - EXPECT_EQ(0u, FXSYS_wcslen(cstr)); -} - -TEST(fxcrt, WidStringInitializerList) { - CFX_WideString many_str({L"clams", L" and ", L"oysters"}); - EXPECT_EQ(L"clams and oysters", many_str); - many_str = {L"fish", L" and ", L"chips", L" and ", L"soda"}; - EXPECT_EQ(L"fish and chips and soda", many_str); -} - -TEST(fxcrt, WideStringNullIterator) { - CFX_WideString null_str; - int32_t sum = 0; - bool any_present = false; - for (const auto& c : null_str) { - sum += c; // Avoid unused arg warnings. - any_present = true; - } - EXPECT_FALSE(any_present); - EXPECT_EQ(0, sum); -} - -TEST(fxcrt, WideStringEmptyIterator) { - CFX_WideString empty_str(L""); - int32_t sum = 0; - bool any_present = false; - for (const auto& c : empty_str) { - any_present = true; - sum += c; // Avoid unused arg warnings. - } - EXPECT_FALSE(any_present); - EXPECT_EQ(0, sum); -} - -TEST(fxcrt, WideStringOneCharIterator) { - CFX_WideString one_str(L"a"); - int32_t sum = 0; - bool any_present = false; - for (const auto& c : one_str) { - any_present = true; - sum += c; // Avoid unused arg warnings. - } - EXPECT_TRUE(any_present); - EXPECT_EQ(static_cast(L'a'), sum); -} - -TEST(fxcrt, WideStringMultiCharIterator) { - CFX_WideString one_str(L"abc"); - int32_t sum = 0; - bool any_present = false; - for (const auto& c : one_str) { - any_present = true; - sum += c; // Avoid unused arg warnings. - } - EXPECT_TRUE(any_present); - EXPECT_EQ(static_cast(L'a' + L'b' + L'c'), sum); -} - -TEST(fxcrt, WideStringAnyAllNoneOf) { - CFX_WideString str(L"aaaaaaaaaaaaaaaaab"); - EXPECT_FALSE(std::all_of(str.begin(), str.end(), - [](const wchar_t& c) { return c == L'a'; })); - - EXPECT_FALSE(std::none_of(str.begin(), str.end(), - [](const wchar_t& c) { return c == L'a'; })); - - EXPECT_TRUE(std::any_of(str.begin(), str.end(), - [](const wchar_t& c) { return c == L'a'; })); - - EXPECT_TRUE(pdfium::ContainsValue(str, L'a')); - EXPECT_TRUE(pdfium::ContainsValue(str, L'b')); - EXPECT_FALSE(pdfium::ContainsValue(str, L'z')); -} - -TEST(fxcrt, OStreamWideStringOverload) { - std::ostringstream stream; - - // Basic case, empty string - CFX_WideString str; - stream << str; - EXPECT_EQ("", stream.str()); - - // Basic case, wide character - str = L"\u20AC"; - stream << str; - EXPECT_EQ("\u20AC", stream.str()); - - // Basic case, non-empty string - str = L"def"; - stream.str(""); - stream << "abc" << str << "ghi"; - EXPECT_EQ("abcdefghi", stream.str()); - - // Changing the CFX_WideString does not change the stream it was written to. - str = L"123"; - EXPECT_EQ("abcdefghi", stream.str()); - - // Writing it again to the stream will use the latest value. - stream.str(""); - stream << "abc" << str << "ghi"; - EXPECT_EQ("abc123ghi", stream.str()); - - wchar_t stringWithNulls[]{'x', 'y', '\0', 'z'}; - - // Writing a CFX_WideString with nulls and no specified length treats it as - // a C-style null-terminated string. - str = CFX_WideString(stringWithNulls); - EXPECT_EQ(2u, str.GetLength()); - stream.str(""); - stream << str; - EXPECT_EQ(2u, stream.tellp()); - - // Writing a CFX_WideString with nulls but specifying its length treats it as - // a C++-style string. - str = CFX_WideString(stringWithNulls, 4); - EXPECT_EQ(4u, str.GetLength()); - stream.str(""); - stream << str; - EXPECT_EQ(4u, stream.tellp()); - - // << operators can be chained. - CFX_WideString str1(L"abc"); - CFX_WideString str2(L"def"); - stream.str(""); - stream << str1 << str2; - EXPECT_EQ("abcdef", stream.str()); -} - -TEST(fxcrt, WideOStreamWideStringOverload) { - std::wostringstream stream; - - // Basic case, empty string - CFX_WideString str; - stream << str; - EXPECT_EQ(L"", stream.str()); - - // Basic case, wide character - str = L"\u20AC"; - stream << str; - EXPECT_EQ(L"\u20AC", stream.str()); - - // Basic case, non-empty string - str = L"def"; - stream.str(L""); - stream << L"abc" << str << L"ghi"; - EXPECT_EQ(L"abcdefghi", stream.str()); - - // Changing the CFX_WideString does not change the stream it was written to. - str = L"123"; - EXPECT_EQ(L"abcdefghi", stream.str()); - - // Writing it again to the stream will use the latest value. - stream.str(L""); - stream << L"abc" << str << L"ghi"; - EXPECT_EQ(L"abc123ghi", stream.str()); - - wchar_t stringWithNulls[]{'x', 'y', '\0', 'z'}; - - // Writing a CFX_WideString with nulls and no specified length treats it as - // a C-style null-terminated string. - str = CFX_WideString(stringWithNulls); - EXPECT_EQ(2u, str.GetLength()); - stream.str(L""); - stream << str; - EXPECT_EQ(2u, stream.tellp()); - - // Writing a CFX_WideString with nulls but specifying its length treats it as - // a C++-style string. - str = CFX_WideString(stringWithNulls, 4); - EXPECT_EQ(4u, str.GetLength()); - stream.str(L""); - stream << str; - EXPECT_EQ(4u, stream.tellp()); - - // << operators can be chained. - CFX_WideString str1(L"abc"); - CFX_WideString str2(L"def"); - stream.str(L""); - stream << str1 << str2; - EXPECT_EQ(L"abcdef", stream.str()); -} - -TEST(fxcrt, OStreamWideStringCOverload) { - // Basic case, empty string - { - std::ostringstream stream; - CFX_WideStringC str; - stream << str; - EXPECT_EQ("", stream.str()); - } - - // Basic case, non-empty string - { - std::ostringstream stream; - CFX_WideStringC str(L"def"); - stream << "abc" << str << "ghi"; - EXPECT_EQ("abcdefghi", stream.str()); - } - - // Basic case, wide character - { - std::ostringstream stream; - CFX_WideStringC str(L"\u20AC"); - stream << str; - EXPECT_EQ("\u20AC", stream.str()); - } - - // Changing the CFX_WideStringC does not change the stream it was written to. - { - std::ostringstream stream; - CFX_WideStringC str(L"abc"); - stream << str; - str = L"123"; - EXPECT_EQ("abc", stream.str()); - } - - // Writing it again to the stream will use the latest value. - { - std::ostringstream stream; - CFX_WideStringC str(L"abc"); - stream << str; - stream.str(""); - str = L"123"; - stream << str; - EXPECT_EQ("123", stream.str()); - } - - // Writing a CFX_WideStringC with nulls and no specified length treats it as - // a C-style null-terminated string. - { - wchar_t stringWithNulls[]{'x', 'y', '\0', 'z'}; - std::ostringstream stream; - CFX_WideStringC str(stringWithNulls); - EXPECT_EQ(2u, str.GetLength()); - stream << str; - EXPECT_EQ(2u, stream.tellp()); - str = L""; - } - - // Writing a CFX_WideStringC with nulls but specifying its length treats it as - // a C++-style string. - { - wchar_t stringWithNulls[]{'x', 'y', '\0', 'z'}; - std::ostringstream stream; - CFX_WideStringC str(stringWithNulls, 4); - EXPECT_EQ(4u, str.GetLength()); - stream << str; - EXPECT_EQ(4u, stream.tellp()); - str = L""; - } - - // << operators can be chained. - { - std::ostringstream stream; - CFX_WideStringC str1(L"abc"); - CFX_WideStringC str2(L"def"); - stream << str1 << str2; - EXPECT_EQ("abcdef", stream.str()); - } -} - -TEST(fxcrt, WideOStreamWideStringCOverload) { - // Basic case, empty string - { - std::wostringstream stream; - CFX_WideStringC str; - stream << str; - EXPECT_EQ(L"", stream.str()); - } - - // Basic case, non-empty string - { - std::wostringstream stream; - CFX_WideStringC str(L"def"); - stream << "abc" << str << "ghi"; - EXPECT_EQ(L"abcdefghi", stream.str()); - } - - // Basic case, wide character - { - std::wostringstream stream; - CFX_WideStringC str(L"\u20AC"); - stream << str; - EXPECT_EQ(L"\u20AC", stream.str()); - } - - // Changing the CFX_WideStringC does not change the stream it was written to. - { - std::wostringstream stream; - CFX_WideStringC str(L"abc"); - stream << str; - str = L"123"; - EXPECT_EQ(L"abc", stream.str()); - } - - // Writing it again to the stream will use the latest value. - { - std::wostringstream stream; - CFX_WideStringC str(L"abc"); - stream << str; - stream.str(L""); - str = L"123"; - stream << str; - EXPECT_EQ(L"123", stream.str()); - } - - // Writing a CFX_WideStringC with nulls and no specified length treats it as - // a C-style null-terminated string. - { - wchar_t stringWithNulls[]{'x', 'y', '\0', 'z'}; - std::wostringstream stream; - CFX_WideStringC str(stringWithNulls); - EXPECT_EQ(2u, str.GetLength()); - stream << str; - EXPECT_EQ(2u, stream.tellp()); - } - - // Writing a CFX_WideStringC with nulls but specifying its length treats it as - // a C++-style string. - { - wchar_t stringWithNulls[]{'x', 'y', '\0', 'z'}; - std::wostringstream stream; - CFX_WideStringC str(stringWithNulls, 4); - EXPECT_EQ(4u, str.GetLength()); - stream << str; - EXPECT_EQ(4u, stream.tellp()); - } - - // << operators can be chained. - { - std::wostringstream stream; - CFX_WideStringC str1(L"abc"); - CFX_WideStringC str2(L"def"); - stream << str1 << str2; - EXPECT_EQ(L"abcdef", stream.str()); - } -} diff --git a/core/fxcrt/cfx_widetextbuf.cpp b/core/fxcrt/cfx_widetextbuf.cpp index 81b5fd4b05..d51e5ea314 100644 --- a/core/fxcrt/cfx_widetextbuf.cpp +++ b/core/fxcrt/cfx_widetextbuf.cpp @@ -16,12 +16,12 @@ void CFX_WideTextBuf::AppendChar(wchar_t ch) { m_DataSize += sizeof(wchar_t); } -CFX_WideTextBuf& CFX_WideTextBuf::operator<<(const CFX_WideStringC& str) { +CFX_WideTextBuf& CFX_WideTextBuf::operator<<(const WideStringView& str) { AppendBlock(str.unterminated_c_str(), str.GetLength() * sizeof(wchar_t)); return *this; } -CFX_WideTextBuf& CFX_WideTextBuf::operator<<(const CFX_WideString& str) { +CFX_WideTextBuf& CFX_WideTextBuf::operator<<(const WideString& str) { AppendBlock(str.c_str(), str.GetLength() * sizeof(wchar_t)); return *this; } diff --git a/core/fxcrt/cfx_widetextbuf.h b/core/fxcrt/cfx_widetextbuf.h index 389f2e52a3..77fe4141f9 100644 --- a/core/fxcrt/cfx_widetextbuf.h +++ b/core/fxcrt/cfx_widetextbuf.h @@ -19,14 +19,14 @@ class CFX_WideTextBuf : public CFX_BinaryBuf { return reinterpret_cast(m_pBuffer.get()); } - CFX_WideStringC AsStringC() const { - return CFX_WideStringC(reinterpret_cast(m_pBuffer.get()), - m_DataSize / sizeof(wchar_t)); - } - CFX_WideString MakeString() const { - return CFX_WideString(reinterpret_cast(m_pBuffer.get()), + WideStringView AsStringView() const { + return WideStringView(reinterpret_cast(m_pBuffer.get()), m_DataSize / sizeof(wchar_t)); } + WideString MakeString() const { + return WideString(reinterpret_cast(m_pBuffer.get()), + m_DataSize / sizeof(wchar_t)); + } void Delete(int start_index, int count) { CFX_BinaryBuf::Delete(start_index * sizeof(wchar_t), @@ -36,8 +36,8 @@ class CFX_WideTextBuf : public CFX_BinaryBuf { CFX_WideTextBuf& operator<<(int i); CFX_WideTextBuf& operator<<(double f); CFX_WideTextBuf& operator<<(const wchar_t* lpsz); - CFX_WideTextBuf& operator<<(const CFX_WideStringC& str); - CFX_WideTextBuf& operator<<(const CFX_WideString& str); + CFX_WideTextBuf& operator<<(const WideStringView& str); + CFX_WideTextBuf& operator<<(const WideString& str); CFX_WideTextBuf& operator<<(const CFX_WideTextBuf& buf); }; diff --git a/core/fxcrt/css/cfx_csscomputedstyle.cpp b/core/fxcrt/css/cfx_csscomputedstyle.cpp index 953c107ec3..aae88a364a 100644 --- a/core/fxcrt/css/cfx_csscomputedstyle.cpp +++ b/core/fxcrt/css/cfx_csscomputedstyle.cpp @@ -14,8 +14,8 @@ CFX_CSSComputedStyle::CFX_CSSComputedStyle() {} CFX_CSSComputedStyle::~CFX_CSSComputedStyle() {} -bool CFX_CSSComputedStyle::GetCustomStyle(const CFX_WideString& wsName, - CFX_WideString& wsValue) const { +bool CFX_CSSComputedStyle::GetCustomStyle(const WideString& wsName, + WideString& wsValue) const { for (auto iter = m_CustomProperties.rbegin(); iter != m_CustomProperties.rend(); iter++) { if (wsName == iter->name()) { @@ -32,7 +32,7 @@ int32_t CFX_CSSComputedStyle::CountFontFamilies() const { : 0; } -const CFX_WideString CFX_CSSComputedStyle::GetFontFamily(int32_t index) const { +const WideString CFX_CSSComputedStyle::GetFontFamily(int32_t index) const { return m_InheritedData.m_pFontFamily->GetValue(index) .As() ->Value(); diff --git a/core/fxcrt/css/cfx_csscomputedstyle.h b/core/fxcrt/css/cfx_csscomputedstyle.h index bb4b62bc2b..b05339ac02 100644 --- a/core/fxcrt/css/cfx_csscomputedstyle.h +++ b/core/fxcrt/css/cfx_csscomputedstyle.h @@ -56,7 +56,7 @@ class CFX_CSSComputedStyle : public CFX_Retainable { }; int32_t CountFontFamilies() const; - const CFX_WideString GetFontFamily(int32_t index) const; + const WideString GetFontFamily(int32_t index) const; uint16_t GetFontWeight() const; CFX_CSSFontVariant GetFontVariant() const; CFX_CSSFontStyle GetFontStyle() const; @@ -91,8 +91,7 @@ class CFX_CSSComputedStyle : public CFX_Retainable { void SetLetterSpacing(const CFX_CSSLength& letterSpacing); void AddCustomStyle(const CFX_CSSCustomProperty& prop); - bool GetCustomStyle(const CFX_WideString& wsName, - CFX_WideString& wsValue) const; + bool GetCustomStyle(const WideString& wsName, WideString& wsValue) const; InheritedData m_InheritedData; NonInheritedData m_NonInheritedData; diff --git a/core/fxcrt/css/cfx_csscustomproperty.cpp b/core/fxcrt/css/cfx_csscustomproperty.cpp index 8bfb9d961e..353facd5f0 100644 --- a/core/fxcrt/css/cfx_csscustomproperty.cpp +++ b/core/fxcrt/css/cfx_csscustomproperty.cpp @@ -4,8 +4,8 @@ #include "core/fxcrt/css/cfx_csscustomproperty.h" -CFX_CSSCustomProperty::CFX_CSSCustomProperty(const CFX_WideString& name, - const CFX_WideString& value) +CFX_CSSCustomProperty::CFX_CSSCustomProperty(const WideString& name, + const WideString& value) : name_(name), value_(value) {} CFX_CSSCustomProperty::CFX_CSSCustomProperty(const CFX_CSSCustomProperty& prop) diff --git a/core/fxcrt/css/cfx_csscustomproperty.h b/core/fxcrt/css/cfx_csscustomproperty.h index e062c3e953..15c3eca124 100644 --- a/core/fxcrt/css/cfx_csscustomproperty.h +++ b/core/fxcrt/css/cfx_csscustomproperty.h @@ -11,17 +11,16 @@ class CFX_CSSCustomProperty { public: - CFX_CSSCustomProperty(const CFX_WideString& name, - const CFX_WideString& value); + CFX_CSSCustomProperty(const WideString& name, const WideString& value); CFX_CSSCustomProperty(const CFX_CSSCustomProperty& prop); ~CFX_CSSCustomProperty(); - CFX_WideString name() const { return name_; } - CFX_WideString value() const { return value_; } + WideString name() const { return name_; } + WideString value() const { return value_; } private: - CFX_WideString name_; - CFX_WideString value_; + WideString name_; + WideString value_; }; #endif // CORE_FXCRT_CSS_CFX_CSSCUSTOMPROPERTY_H_ diff --git a/core/fxcrt/css/cfx_cssdatatable.cpp b/core/fxcrt/css/cfx_cssdatatable.cpp index 833b81b93b..53617b6a48 100644 --- a/core/fxcrt/css/cfx_cssdatatable.cpp +++ b/core/fxcrt/css/cfx_cssdatatable.cpp @@ -122,7 +122,7 @@ static_assert(g_iCSSPropertyCount == "Property table differs in size from property enum"); const CFX_CSSPropertyTable* CFX_GetCSSPropertyByName( - const CFX_WideStringC& wsName) { + const WideStringView& wsName) { ASSERT(!wsName.IsEmpty()); uint32_t dwHash = FX_HashCode_GetW(wsName, true); int32_t iEnd = g_iCSSPropertyCount; diff --git a/core/fxcrt/css/cfx_cssdatatable.h b/core/fxcrt/css/cfx_cssdatatable.h index 43310c7d5c..63c303488e 100644 --- a/core/fxcrt/css/cfx_cssdatatable.h +++ b/core/fxcrt/css/cfx_cssdatatable.h @@ -23,7 +23,7 @@ struct CFX_CSSPropertyTable { }; const CFX_CSSPropertyTable* CFX_GetCSSPropertyByName( - const CFX_WideStringC& wsName); + const WideStringView& wsName); const CFX_CSSPropertyTable* CFX_GetCSSPropertyByEnum(CFX_CSSProperty eName); #endif // CORE_FXCRT_CSS_CFX_CSSDATATABLE_H_ diff --git a/core/fxcrt/css/cfx_cssdeclaration.cpp b/core/fxcrt/css/cfx_cssdeclaration.cpp index 344fc842c4..f2c7d3930b 100644 --- a/core/fxcrt/css/cfx_cssdeclaration.cpp +++ b/core/fxcrt/css/cfx_cssdeclaration.cpp @@ -113,7 +113,7 @@ const CFX_CSSColorTable g_CFX_CSSColors[] = { }; const CFX_CSSPropertyValueTable* GetCSSPropertyValueByName( - const CFX_WideStringC& wsName) { + const WideStringView& wsName) { ASSERT(!wsName.IsEmpty()); uint32_t dwHash = FX_HashCode_GetW(wsName, true); int32_t iEnd = g_iCSSPropertyValueCount; @@ -134,7 +134,7 @@ const CFX_CSSPropertyValueTable* GetCSSPropertyValueByName( } const CFX_CSSLengthUnitTable* GetCSSLengthUnitByName( - const CFX_WideStringC& wsName) { + const WideStringView& wsName) { ASSERT(!wsName.IsEmpty()); uint16_t wHash = FX_HashCode_GetW(wsName, true); int32_t iEnd = @@ -155,7 +155,7 @@ const CFX_CSSLengthUnitTable* GetCSSLengthUnitByName( return nullptr; } -const CFX_CSSColorTable* GetCSSColorByName(const CFX_WideStringC& wsName) { +const CFX_CSSColorTable* GetCSSColorByName(const WideStringView& wsName) { ASSERT(!wsName.IsEmpty()); uint32_t dwHash = FX_HashCode_GetW(wsName, true); int32_t iEnd = sizeof(g_CFX_CSSColors) / sizeof(CFX_CSSColorTable) - 1; @@ -192,7 +192,7 @@ bool ParseCSSNumber(const wchar_t* pszValue, eUnit = CFX_CSSNumberType::Percent; } else if (iValueLen == 2) { const CFX_CSSLengthUnitTable* pUnit = - GetCSSLengthUnitByName(CFX_WideStringC(pszValue, 2)); + GetCSSLengthUnitByName(WideStringView(pszValue, 2)); if (pUnit) eUnit = pUnit->wValue; } @@ -273,7 +273,7 @@ bool CFX_CSSDeclaration::ParseCSSColor(const wchar_t* pszValue, } const CFX_CSSColorTable* pColor = - GetCSSColorByName(CFX_WideStringC(pszValue, iValueLen)); + GetCSSColorByName(WideStringView(pszValue, iValueLen)); if (!pColor) return false; @@ -308,7 +308,7 @@ void CFX_CSSDeclaration::AddPropertyHolder(CFX_CSSProperty eProperty, } void CFX_CSSDeclaration::AddProperty(const CFX_CSSPropertyTable* pTable, - const CFX_WideStringC& value) { + const WideStringView& value) { ASSERT(!value.IsEmpty()); const wchar_t* pszValue = value.unterminated_c_str(); @@ -422,8 +422,8 @@ void CFX_CSSDeclaration::AddProperty(const CFX_CSSPropertyTable* pTable, } } -void CFX_CSSDeclaration::AddProperty(const CFX_WideString& prop, - const CFX_WideString& value) { +void CFX_CSSDeclaration::AddProperty(const WideString& prop, + const WideString& value) { custom_properties_.push_back( pdfium::MakeUnique(prop, value)); } @@ -442,7 +442,7 @@ CFX_RetainPtr CFX_CSSDeclaration::ParseEnum( const wchar_t* pszValue, int32_t iValueLen) { const CFX_CSSPropertyValueTable* pValue = - GetCSSPropertyValueByName(CFX_WideStringC(pszValue, iValueLen)); + GetCSSPropertyValueByName(WideStringView(pszValue, iValueLen)); return pValue ? pdfium::MakeRetain(pValue->eName) : nullptr; } @@ -466,7 +466,7 @@ CFX_RetainPtr CFX_CSSDeclaration::ParseString( return nullptr; return pdfium::MakeRetain( - CFX_WideString(pszValue + iOffset, iValueLen)); + WideString(pszValue + iOffset, iValueLen)); } void CFX_CSSDeclaration::ParseValueListProperty( @@ -502,7 +502,7 @@ void CFX_CSSDeclaration::ParseValueListProperty( } if (dwType & CFX_CSSVALUETYPE_MaybeEnum) { const CFX_CSSPropertyValueTable* pValue = - GetCSSPropertyValueByName(CFX_WideStringC(pszValue, iValueLen)); + GetCSSPropertyValueByName(WideStringView(pszValue, iValueLen)); if (pValue) { list.push_back(pdfium::MakeRetain(pValue->eName)); continue; @@ -510,7 +510,7 @@ void CFX_CSSDeclaration::ParseValueListProperty( } if (dwType & CFX_CSSVALUETYPE_MaybeString) { list.push_back(pdfium::MakeRetain( - CFX_WideString(pszValue, iValueLen))); + WideString(pszValue, iValueLen))); } break; case CFX_CSSPrimitiveType::RGB: @@ -614,12 +614,12 @@ bool CFX_CSSDeclaration::ParseBorderProperty( } case CFX_CSSPrimitiveType::String: { const CFX_CSSColorTable* pColorItem = - GetCSSColorByName(CFX_WideStringC(pszValue, iValueLen)); + GetCSSColorByName(WideStringView(pszValue, iValueLen)); if (pColorItem) continue; const CFX_CSSPropertyValueTable* pValue = - GetCSSPropertyValueByName(CFX_WideStringC(pszValue, iValueLen)); + GetCSSPropertyValueByName(WideStringView(pszValue, iValueLen)); if (!pValue) continue; @@ -661,7 +661,7 @@ void CFX_CSSDeclaration::ParseFontProperty(const wchar_t* pszValue, switch (eType) { case CFX_CSSPrimitiveType::String: { const CFX_CSSPropertyValueTable* pValue = - GetCSSPropertyValueByName(CFX_WideStringC(pszValue, iValueLen)); + GetCSSPropertyValueByName(WideStringView(pszValue, iValueLen)); if (pValue) { switch (pValue->eName) { case CFX_CSSPropertyValue::XxSmall: @@ -710,7 +710,7 @@ void CFX_CSSDeclaration::ParseFontProperty(const wchar_t* pszValue, } if (pFontSize) { familyList.push_back(pdfium::MakeRetain( - CFX_WideString(pszValue, iValueLen))); + WideString(pszValue, iValueLen))); } parser.m_Separator = ','; break; diff --git a/core/fxcrt/css/cfx_cssdeclaration.h b/core/fxcrt/css/cfx_cssdeclaration.h index 7b39daef7e..dba1d44fc7 100644 --- a/core/fxcrt/css/cfx_cssdeclaration.h +++ b/core/fxcrt/css/cfx_cssdeclaration.h @@ -48,8 +48,8 @@ class CFX_CSSDeclaration { bool empty() const { return properties_.empty(); } void AddProperty(const CFX_CSSPropertyTable* pTable, - const CFX_WideStringC& value); - void AddProperty(const CFX_WideString& prop, const CFX_WideString& value); + const WideStringView& value); + void AddProperty(const WideString& prop, const WideString& value); size_t PropertyCountForTesting() const; diff --git a/core/fxcrt/css/cfx_cssrulecollection.cpp b/core/fxcrt/css/cfx_cssrulecollection.cpp index 635ca91c72..2030518b69 100644 --- a/core/fxcrt/css/cfx_cssrulecollection.cpp +++ b/core/fxcrt/css/cfx_cssrulecollection.cpp @@ -28,7 +28,7 @@ void CFX_CSSRuleCollection::Clear() { } const std::vector>* -CFX_CSSRuleCollection::GetTagRuleData(const CFX_WideString& tagname) const { +CFX_CSSRuleCollection::GetTagRuleData(const WideString& tagname) const { auto it = m_TagRules.find(FX_HashCode_GetW(tagname.c_str(), true)); return it != m_TagRules.end() ? &it->second : nullptr; } diff --git a/core/fxcrt/css/cfx_cssrulecollection.h b/core/fxcrt/css/cfx_cssrulecollection.h index 6b91c6bcd5..72ae58c55f 100644 --- a/core/fxcrt/css/cfx_cssrulecollection.h +++ b/core/fxcrt/css/cfx_cssrulecollection.h @@ -36,7 +36,7 @@ class CFX_CSSRuleCollection { int32_t CountSelectors() const { return m_iSelectors; } const std::vector>* GetTagRuleData( - const CFX_WideString& tagname) const; + const WideString& tagname) const; private: void AddRulesFrom(const CFX_CSSStyleSheet* pStyleSheet, diff --git a/core/fxcrt/css/cfx_cssselector.cpp b/core/fxcrt/css/cfx_cssselector.cpp index 6ee81f5610..3993dcae5c 100644 --- a/core/fxcrt/css/cfx_cssselector.cpp +++ b/core/fxcrt/css/cfx_cssselector.cpp @@ -31,7 +31,7 @@ CFX_CSSSelector::CFX_CSSSelector(CFX_CSSSelectorType eType, int32_t iLen, bool bIgnoreCase) : m_eType(eType), - m_dwHash(FX_HashCode_GetW(CFX_WideStringC(psz, iLen), bIgnoreCase)) {} + m_dwHash(FX_HashCode_GetW(WideStringView(psz, iLen), bIgnoreCase)) {} CFX_CSSSelector::~CFX_CSSSelector() {} @@ -49,7 +49,7 @@ CFX_CSSSelector* CFX_CSSSelector::GetNextSelector() const { // static. std::unique_ptr CFX_CSSSelector::FromString( - const CFX_WideStringC& str) { + const WideStringView& str) { ASSERT(!str.IsEmpty()); const wchar_t* psz = str.unterminated_c_str(); diff --git a/core/fxcrt/css/cfx_cssselector.h b/core/fxcrt/css/cfx_cssselector.h index 9fff42a850..62f8b166cc 100644 --- a/core/fxcrt/css/cfx_cssselector.h +++ b/core/fxcrt/css/cfx_cssselector.h @@ -15,8 +15,7 @@ class CFX_CSSSelector { public: - static std::unique_ptr FromString( - const CFX_WideStringC& str); + static std::unique_ptr FromString(const WideStringView& str); CFX_CSSSelector(CFX_CSSSelectorType eType, const wchar_t* psz, diff --git a/core/fxcrt/css/cfx_cssstringvalue.cpp b/core/fxcrt/css/cfx_cssstringvalue.cpp index b66c54505f..6ff2a33c9b 100644 --- a/core/fxcrt/css/cfx_cssstringvalue.cpp +++ b/core/fxcrt/css/cfx_cssstringvalue.cpp @@ -6,7 +6,7 @@ #include "core/fxcrt/css/cfx_cssstringvalue.h" -CFX_CSSStringValue::CFX_CSSStringValue(const CFX_WideString& value) +CFX_CSSStringValue::CFX_CSSStringValue(const WideString& value) : CFX_CSSValue(CFX_CSSPrimitiveType::String), value_(value) {} CFX_CSSStringValue::~CFX_CSSStringValue() {} diff --git a/core/fxcrt/css/cfx_cssstringvalue.h b/core/fxcrt/css/cfx_cssstringvalue.h index 7680360973..d72078a630 100644 --- a/core/fxcrt/css/cfx_cssstringvalue.h +++ b/core/fxcrt/css/cfx_cssstringvalue.h @@ -11,13 +11,13 @@ class CFX_CSSStringValue : public CFX_CSSValue { public: - explicit CFX_CSSStringValue(const CFX_WideString& value); + explicit CFX_CSSStringValue(const WideString& value); ~CFX_CSSStringValue() override; - const CFX_WideString Value() const { return value_; } + const WideString Value() const { return value_; } private: - const CFX_WideString value_; + const WideString value_; }; #endif // CORE_FXCRT_CSS_CFX_CSSSTRINGVALUE_H_ diff --git a/core/fxcrt/css/cfx_cssstyleselector.cpp b/core/fxcrt/css/cfx_cssstyleselector.cpp index 9a2bc8c498..9ae2b876f7 100644 --- a/core/fxcrt/css/cfx_cssstyleselector.cpp +++ b/core/fxcrt/css/cfx_cssstyleselector.cpp @@ -50,7 +50,7 @@ void CFX_CSSStyleSelector::UpdateStyleIndex() { } std::vector CFX_CSSStyleSelector::MatchDeclarations( - const CFX_WideString& tagname) { + const WideString& tagname) { std::vector matchedDecls; if (m_UARules.CountSelectors() == 0 || tagname.IsEmpty()) return matchedDecls; @@ -66,7 +66,7 @@ std::vector CFX_CSSStyleSelector::MatchDeclarations( return matchedDecls; } -bool CFX_CSSStyleSelector::MatchSelector(const CFX_WideString& tagname, +bool CFX_CSSStyleSelector::MatchSelector(const WideString& tagname, CFX_CSSSelector* pSel) { // TODO(dsinclair): The code only supports a single level of selector at this // point. None of the code using selectors required the complexity so lets @@ -80,8 +80,8 @@ bool CFX_CSSStyleSelector::MatchSelector(const CFX_WideString& tagname, void CFX_CSSStyleSelector::ComputeStyle( const std::vector& declArray, - const CFX_WideString& styleString, - const CFX_WideString& alignString, + const WideString& styleString, + const WideString& alignString, CFX_CSSComputedStyle* pDest) { std::unique_ptr pDecl; if (!styleString.IsEmpty() || !alignString.IsEmpty()) { @@ -91,7 +91,7 @@ void CFX_CSSStyleSelector::ComputeStyle( AppendInlineStyle(pDecl.get(), styleString); if (!alignString.IsEmpty()) { pDecl->AddProperty(CFX_GetCSSPropertyByEnum(CFX_CSSProperty::TextAlign), - alignString.AsStringC()); + alignString.AsStringView()); } } ApplyDeclarations(declArray, pDecl.get(), pDest); @@ -137,29 +137,29 @@ void CFX_CSSStyleSelector::ExtractValues( } void CFX_CSSStyleSelector::AppendInlineStyle(CFX_CSSDeclaration* pDecl, - const CFX_WideString& style) { + const WideString& style) { ASSERT(pDecl && !style.IsEmpty()); auto pSyntax = pdfium::MakeUnique( style.c_str(), style.GetLength(), 32, true); int32_t iLen2 = 0; const CFX_CSSPropertyTable* table = nullptr; - CFX_WideString wsName; + WideString wsName; while (1) { CFX_CSSSyntaxStatus eStatus = pSyntax->DoSyntaxParse(); if (eStatus == CFX_CSSSyntaxStatus::PropertyName) { - CFX_WideStringC strValue = pSyntax->GetCurrentString(); + WideStringView strValue = pSyntax->GetCurrentString(); table = CFX_GetCSSPropertyByName(strValue); if (!table) - wsName = CFX_WideString(strValue); + wsName = WideString(strValue); } else if (eStatus == CFX_CSSSyntaxStatus::PropertyValue) { if (table || iLen2 > 0) { - CFX_WideStringC strValue = pSyntax->GetCurrentString(); + WideStringView strValue = pSyntax->GetCurrentString(); if (!strValue.IsEmpty()) { if (table) pDecl->AddProperty(table, strValue); else if (iLen2 > 0) - pDecl->AddProperty(wsName, CFX_WideString(strValue)); + pDecl->AddProperty(wsName, WideString(strValue)); } } } else { diff --git a/core/fxcrt/css/cfx_cssstyleselector.h b/core/fxcrt/css/cfx_cssstyleselector.h index 143e51ee68..b59e3048d6 100644 --- a/core/fxcrt/css/cfx_cssstyleselector.h +++ b/core/fxcrt/css/cfx_cssstyleselector.h @@ -39,18 +39,17 @@ class CFX_CSSStyleSelector { // adds non-inherited data from the parent style. Attempting to copy // internally will fail as you'll lose the non-inherited data. void ComputeStyle(const std::vector& declArray, - const CFX_WideString& styleString, - const CFX_WideString& alignString, + const WideString& styleString, + const WideString& alignString, CFX_CSSComputedStyle* pDestStyle); std::vector MatchDeclarations( - const CFX_WideString& tagname); + const WideString& tagname); private: - bool MatchSelector(const CFX_WideString& tagname, CFX_CSSSelector* pSel); + bool MatchSelector(const WideString& tagname, CFX_CSSSelector* pSel); - void AppendInlineStyle(CFX_CSSDeclaration* pDecl, - const CFX_WideString& style); + void AppendInlineStyle(CFX_CSSDeclaration* pDecl, const WideString& style); void ApplyDeclarations( const std::vector& declArray, const CFX_CSSDeclaration* extraDecl, diff --git a/core/fxcrt/css/cfx_cssstylesheet.cpp b/core/fxcrt/css/cfx_cssstylesheet.cpp index 9bd25c044f..183765f3b0 100644 --- a/core/fxcrt/css/cfx_cssstylesheet.cpp +++ b/core/fxcrt/css/cfx_cssstylesheet.cpp @@ -63,32 +63,32 @@ CFX_CSSSyntaxStatus CFX_CSSStyleSheet::LoadStyleRule( CFX_CSSStyleRule* pStyleRule = nullptr; int32_t iValueLen = 0; const CFX_CSSPropertyTable* propertyTable = nullptr; - CFX_WideString wsName; + WideString wsName; while (1) { switch (pSyntax->DoSyntaxParse()) { case CFX_CSSSyntaxStatus::Selector: { - CFX_WideStringC strValue = pSyntax->GetCurrentString(); + WideStringView strValue = pSyntax->GetCurrentString(); auto pSelector = CFX_CSSSelector::FromString(strValue); if (pSelector) selectors.push_back(std::move(pSelector)); break; } case CFX_CSSSyntaxStatus::PropertyName: { - CFX_WideStringC strValue = pSyntax->GetCurrentString(); + WideStringView strValue = pSyntax->GetCurrentString(); propertyTable = CFX_GetCSSPropertyByName(strValue); if (!propertyTable) - wsName = CFX_WideString(strValue); + wsName = WideString(strValue); break; } case CFX_CSSSyntaxStatus::PropertyValue: { if (propertyTable || iValueLen > 0) { - CFX_WideStringC strValue = pSyntax->GetCurrentString(); + WideStringView strValue = pSyntax->GetCurrentString(); auto* decl = pStyleRule->GetDeclaration(); if (!strValue.IsEmpty()) { if (propertyTable) { decl->AddProperty(propertyTable, strValue); } else { - decl->AddProperty(wsName, CFX_WideString(strValue)); + decl->AddProperty(wsName, WideString(strValue)); } } } diff --git a/core/fxcrt/css/cfx_cssstylesheet_unittest.cpp b/core/fxcrt/css/cfx_cssstylesheet_unittest.cpp index 4194a70490..abcd2f6972 100644 --- a/core/fxcrt/css/cfx_cssstylesheet_unittest.cpp +++ b/core/fxcrt/css/cfx_cssstylesheet_unittest.cpp @@ -28,7 +28,7 @@ class CFX_CSSStyleSheetTest : public testing::Test { void TearDown() override { decl_ = nullptr; } void LoadAndVerifyDecl(const wchar_t* buf, - const std::vector& selectors, + const std::vector& selectors, size_t decl_count) { ASSERT(sheet_); @@ -39,7 +39,7 @@ class CFX_CSSStyleSheetTest : public testing::Test { EXPECT_EQ(selectors.size(), style->CountSelectorLists()); for (size_t i = 0; i < selectors.size(); i++) { - uint32_t hash = FX_HashCode_GetW(selectors[i].AsStringC(), true); + uint32_t hash = FX_HashCode_GetW(selectors[i].AsStringView(), true); EXPECT_EQ(hash, style->GetSelectorList(i)->GetNameHash()); } diff --git a/core/fxcrt/css/cfx_csssyntaxparser.cpp b/core/fxcrt/css/cfx_csssyntaxparser.cpp index c8082e87fb..066b82b5d6 100644 --- a/core/fxcrt/css/cfx_csssyntaxparser.cpp +++ b/core/fxcrt/css/cfx_csssyntaxparser.cpp @@ -223,6 +223,6 @@ bool CFX_CSSSyntaxParser::RestoreMode() { return true; } -CFX_WideStringC CFX_CSSSyntaxParser::GetCurrentString() const { - return CFX_WideStringC(m_TextData.GetBuffer(), m_iTextDataLen); +WideStringView CFX_CSSSyntaxParser::GetCurrentString() const { + return WideStringView(m_TextData.GetBuffer(), m_iTextDataLen); } diff --git a/core/fxcrt/css/cfx_csssyntaxparser.h b/core/fxcrt/css/cfx_csssyntaxparser.h index 9ddedfe4a7..778f9a3272 100644 --- a/core/fxcrt/css/cfx_csssyntaxparser.h +++ b/core/fxcrt/css/cfx_csssyntaxparser.h @@ -47,7 +47,7 @@ class CFX_CSSSyntaxParser { ~CFX_CSSSyntaxParser(); CFX_CSSSyntaxStatus DoSyntaxParse(); - CFX_WideStringC GetCurrentString() const; + WideStringView GetCurrentString() const; protected: void SwitchMode(CFX_CSSSyntaxMode eMode); diff --git a/core/fxcrt/css/cfx_cssvaluelistparser_unittest.cpp b/core/fxcrt/css/cfx_cssvaluelistparser_unittest.cpp index 510c96251d..62a542bc52 100644 --- a/core/fxcrt/css/cfx_cssvaluelistparser_unittest.cpp +++ b/core/fxcrt/css/cfx_cssvaluelistparser_unittest.cpp @@ -18,25 +18,25 @@ TEST(CFX_CSSValueListParserTest, rgb_short) { auto parser = pdfium::MakeUnique(L"#abc", 4, L' '); EXPECT_TRUE(parser->NextValue(type, start, len)); EXPECT_EQ(CFX_CSSPrimitiveType::RGB, type); - EXPECT_EQ(L"#abc", CFX_WideString(start, len)); + EXPECT_EQ(L"#abc", WideString(start, len)); EXPECT_FALSE(parser->NextValue(type, start, len)); parser = pdfium::MakeUnique(L"#abcdef", 7, L' '); EXPECT_TRUE(parser->NextValue(type, start, len)); EXPECT_EQ(CFX_CSSPrimitiveType::RGB, type); - EXPECT_EQ(L"#abcdef", CFX_WideString(start, len)); + EXPECT_EQ(L"#abcdef", WideString(start, len)); EXPECT_FALSE(parser->NextValue(type, start, len)); parser = pdfium::MakeUnique(L"rgb(1, 255, 4)", 14, L' '); EXPECT_TRUE(parser->NextValue(type, start, len)); EXPECT_EQ(CFX_CSSPrimitiveType::RGB, type); - EXPECT_EQ(L"rgb(1, 255, 4)", CFX_WideString(start, len)); + EXPECT_EQ(L"rgb(1, 255, 4)", WideString(start, len)); parser = pdfium::MakeUnique(L"#abcdefghij", 11, L' '); EXPECT_TRUE(parser->NextValue(type, start, len)); EXPECT_EQ(CFX_CSSPrimitiveType::Unknown, type); - EXPECT_EQ(L"#abcdefghij", CFX_WideString(start, len)); + EXPECT_EQ(L"#abcdefghij", WideString(start, len)); EXPECT_FALSE(parser->NextValue(type, start, len)); } @@ -48,38 +48,38 @@ TEST(CFX_CSSValueListParserTest, number_parsing) { auto parser = pdfium::MakeUnique(L"1234", 4, L' '); EXPECT_TRUE(parser->NextValue(type, start, len)); EXPECT_EQ(CFX_CSSPrimitiveType::Number, type); - EXPECT_EQ(L"1234", CFX_WideString(start, len)); + EXPECT_EQ(L"1234", WideString(start, len)); parser = pdfium::MakeUnique(L"-1234", 5, L' '); EXPECT_TRUE(parser->NextValue(type, start, len)); EXPECT_EQ(CFX_CSSPrimitiveType::Number, type); - EXPECT_EQ(L"-1234", CFX_WideString(start, len)); + EXPECT_EQ(L"-1234", WideString(start, len)); parser = pdfium::MakeUnique(L"+1234", 5, L' '); EXPECT_TRUE(parser->NextValue(type, start, len)); EXPECT_EQ(CFX_CSSPrimitiveType::Number, type); - EXPECT_EQ(L"+1234", CFX_WideString(start, len)); + EXPECT_EQ(L"+1234", WideString(start, len)); parser = pdfium::MakeUnique(L".1234", 5, L' '); EXPECT_TRUE(parser->NextValue(type, start, len)); EXPECT_EQ(CFX_CSSPrimitiveType::Number, type); - EXPECT_EQ(L".1234", CFX_WideString(start, len)); + EXPECT_EQ(L".1234", WideString(start, len)); parser = pdfium::MakeUnique(L"4321.1234", 9, L' '); EXPECT_TRUE(parser->NextValue(type, start, len)); EXPECT_EQ(CFX_CSSPrimitiveType::Number, type); - EXPECT_EQ(L"4321.1234", CFX_WideString(start, len)); + EXPECT_EQ(L"4321.1234", WideString(start, len)); // TODO(dsinclair): These should probably fail but currently don't. parser = pdfium::MakeUnique(L"4321.12.34", 10, L' '); EXPECT_TRUE(parser->NextValue(type, start, len)); EXPECT_EQ(CFX_CSSPrimitiveType::Number, type); - EXPECT_EQ(L"4321.12.34", CFX_WideString(start, len)); + EXPECT_EQ(L"4321.12.34", WideString(start, len)); parser = pdfium::MakeUnique(L"43a1.12.34", 10, L' '); EXPECT_TRUE(parser->NextValue(type, start, len)); EXPECT_EQ(CFX_CSSPrimitiveType::Number, type); - EXPECT_EQ(L"43a1.12.34", CFX_WideString(start, len)); + EXPECT_EQ(L"43a1.12.34", WideString(start, len)); } TEST(CFX_CSSValueListParserTest, string_parsing) { @@ -91,18 +91,18 @@ TEST(CFX_CSSValueListParserTest, string_parsing) { pdfium::MakeUnique(L"'string'", 8, L' '); EXPECT_TRUE(parser->NextValue(type, start, len)); EXPECT_EQ(CFX_CSSPrimitiveType::String, type); - EXPECT_EQ(L"string", CFX_WideString(start, len)); + EXPECT_EQ(L"string", WideString(start, len)); parser = pdfium::MakeUnique(L"\"another string\"", 16, L' '); EXPECT_TRUE(parser->NextValue(type, start, len)); EXPECT_EQ(CFX_CSSPrimitiveType::String, type); - EXPECT_EQ(L"another string", CFX_WideString(start, len)); + EXPECT_EQ(L"another string", WideString(start, len)); parser = pdfium::MakeUnique(L"standalone", 10, L' '); EXPECT_TRUE(parser->NextValue(type, start, len)); EXPECT_EQ(CFX_CSSPrimitiveType::String, type); - EXPECT_EQ(L"standalone", CFX_WideString(start, len)); + EXPECT_EQ(L"standalone", WideString(start, len)); } TEST(CFX_CSSValueListParserTest, multiparsing) { @@ -113,15 +113,15 @@ TEST(CFX_CSSValueListParserTest, multiparsing) { auto parser = pdfium::MakeUnique(L"1, 2, 3", 7, L','); EXPECT_TRUE(parser->NextValue(type, start, len)); EXPECT_EQ(CFX_CSSPrimitiveType::Number, type); - EXPECT_EQ(L"1", CFX_WideString(start, len)); + EXPECT_EQ(L"1", WideString(start, len)); EXPECT_TRUE(parser->NextValue(type, start, len)); EXPECT_EQ(CFX_CSSPrimitiveType::Number, type); - EXPECT_EQ(L"2", CFX_WideString(start, len)); + EXPECT_EQ(L"2", WideString(start, len)); EXPECT_TRUE(parser->NextValue(type, start, len)); EXPECT_EQ(CFX_CSSPrimitiveType::Number, type); - EXPECT_EQ(L"3", CFX_WideString(start, len)); + EXPECT_EQ(L"3", WideString(start, len)); EXPECT_FALSE(parser->NextValue(type, start, len)); @@ -129,13 +129,13 @@ TEST(CFX_CSSValueListParserTest, multiparsing) { 22, L','); EXPECT_TRUE(parser->NextValue(type, start, len)); EXPECT_EQ(CFX_CSSPrimitiveType::String, type); - EXPECT_EQ(L"str", CFX_WideString(start, len)); + EXPECT_EQ(L"str", WideString(start, len)); EXPECT_TRUE(parser->NextValue(type, start, len)); EXPECT_EQ(CFX_CSSPrimitiveType::RGB, type); - EXPECT_EQ(L"rgb(1, 2, 3)", CFX_WideString(start, len)); + EXPECT_EQ(L"rgb(1, 2, 3)", WideString(start, len)); EXPECT_TRUE(parser->NextValue(type, start, len)); EXPECT_EQ(CFX_CSSPrimitiveType::Number, type); - EXPECT_EQ(L"4", CFX_WideString(start, len)); + EXPECT_EQ(L"4", WideString(start, len)); } diff --git a/core/fxcrt/fx_bidi.cpp b/core/fxcrt/fx_bidi.cpp index b7c7cacad8..cae0942550 100644 --- a/core/fxcrt/fx_bidi.cpp +++ b/core/fxcrt/fx_bidi.cpp @@ -581,7 +581,7 @@ void CFX_BidiChar::StartNewSegment(CFX_BidiChar::Direction direction) { m_CurrentSegment.direction = direction; } -CFX_BidiString::CFX_BidiString(const CFX_WideString& str) +CFX_BidiString::CFX_BidiString(const WideString& str) : m_Str(str), m_pBidiChar(pdfium::MakeUnique()), m_eOverallDirection(CFX_BidiChar::LEFT) { diff --git a/core/fxcrt/fx_bidi.h b/core/fxcrt/fx_bidi.h index 0dc426b57a..23f5d02dfd 100644 --- a/core/fxcrt/fx_bidi.h +++ b/core/fxcrt/fx_bidi.h @@ -54,7 +54,7 @@ class CFX_BidiString { public: using const_iterator = std::vector::const_iterator; - explicit CFX_BidiString(const CFX_WideString& str); + explicit CFX_BidiString(const WideString& str); ~CFX_BidiString(); // Overall direction is always LEFT or RIGHT, never NEUTRAL. @@ -70,7 +70,7 @@ class CFX_BidiString { const_iterator end() const { return m_Order.end(); } private: - const CFX_WideString m_Str; + const WideString m_Str; std::unique_ptr m_pBidiChar; std::vector m_Order; CFX_BidiChar::Direction m_eOverallDirection; diff --git a/core/fxcrt/fx_extension.cpp b/core/fxcrt/fx_extension.cpp index 7f73a4ccad..4d0adb86ca 100644 --- a/core/fxcrt/fx_extension.cpp +++ b/core/fxcrt/fx_extension.cpp @@ -73,7 +73,7 @@ int32_t FXSYS_wcsnicmp(const wchar_t* s1, const wchar_t* s2, size_t count) { return wch1 - wch2; } -uint32_t FX_HashCode_GetA(const CFX_ByteStringC& str, bool bIgnoreCase) { +uint32_t FX_HashCode_GetA(const ByteStringView& str, bool bIgnoreCase) { uint32_t dwHashCode = 0; if (bIgnoreCase) { for (const auto& c : str) @@ -85,7 +85,7 @@ uint32_t FX_HashCode_GetA(const CFX_ByteStringC& str, bool bIgnoreCase) { return dwHashCode; } -uint32_t FX_HashCode_GetW(const CFX_WideStringC& str, bool bIgnoreCase) { +uint32_t FX_HashCode_GetW(const WideStringView& str, bool bIgnoreCase) { uint32_t dwHashCode = 0; if (bIgnoreCase) { for (const auto& c : str) diff --git a/core/fxcrt/fx_stream.cpp b/core/fxcrt/fx_stream.cpp index c269ec91ed..a04e781d0d 100644 --- a/core/fxcrt/fx_stream.cpp +++ b/core/fxcrt/fx_stream.cpp @@ -95,16 +95,16 @@ bool IFX_SeekableStream::WriteBlock(const void* buffer, size_t size) { return WriteBlock(buffer, GetSize(), size); } -bool IFX_SeekableStream::WriteString(const CFX_ByteStringC& str) { +bool IFX_SeekableStream::WriteString(const ByteStringView& str) { return WriteBlock(str.unterminated_c_str(), str.GetLength()); } FX_FileHandle* FX_OpenFolder(const char* path) { #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ auto pData = pdfium::MakeUnique(); - pData->m_Handle = FindFirstFileExA((CFX_ByteString(path) + "/*.*").c_str(), - FindExInfoStandard, &pData->m_FindData, - FindExSearchNameMatch, nullptr, 0); + pData->m_Handle = + FindFirstFileExA((ByteString(path) + "/*.*").c_str(), FindExInfoStandard, + &pData->m_FindData, FindExSearchNameMatch, nullptr, 0); if (pData->m_Handle == INVALID_HANDLE_VALUE) return nullptr; @@ -116,7 +116,7 @@ FX_FileHandle* FX_OpenFolder(const char* path) { } bool FX_GetNextFile(FX_FileHandle* handle, - CFX_ByteString* filename, + ByteString* filename, bool* bFolder) { if (!handle) return false; diff --git a/core/fxcrt/fx_stream.h b/core/fxcrt/fx_stream.h index abf031dade..08331e9bf0 100644 --- a/core/fxcrt/fx_stream.h +++ b/core/fxcrt/fx_stream.h @@ -29,9 +29,7 @@ typedef DIR FX_FileHandle; #endif // _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ FX_FileHandle* FX_OpenFolder(const char* path); -bool FX_GetNextFile(FX_FileHandle* handle, - CFX_ByteString* filename, - bool* bFolder); +bool FX_GetNextFile(FX_FileHandle* handle, ByteString* filename, bool* bFolder); void FX_CloseFolder(FX_FileHandle* handle); #define FX_FILEMODE_Write 0 @@ -41,7 +39,7 @@ void FX_CloseFolder(FX_FileHandle* handle); class IFX_WriteStream : virtual public CFX_Retainable { public: virtual bool WriteBlock(const void* pData, size_t size) = 0; - virtual bool WriteString(const CFX_ByteStringC& str) = 0; + virtual bool WriteString(const ByteStringView& str) = 0; }; class IFX_ArchiveStream : public IFX_WriteStream { @@ -107,7 +105,7 @@ class IFX_SeekableStream : public IFX_SeekableReadStream, FX_FILESIZE offset, size_t size) override = 0; bool WriteBlock(const void* buffer, size_t size) override; - bool WriteString(const CFX_ByteStringC& str) override; + bool WriteString(const ByteStringView& str) override; bool Flush() override = 0; }; diff --git a/core/fxcrt/fx_string.cpp b/core/fxcrt/fx_string.cpp index 075f29e538..ce4e187837 100644 --- a/core/fxcrt/fx_string.cpp +++ b/core/fxcrt/fx_string.cpp @@ -51,8 +51,8 @@ class CFX_UTF8Encoder { // The data returned by GetResult() is invalidated when this is modified by // appending any data. - CFX_ByteStringC GetResult() const { - return CFX_ByteStringC(m_Buffer.data(), m_Buffer.size()); + ByteStringView GetResult() const { + return ByteStringView(m_Buffer.data(), m_Buffer.size()); } private: @@ -61,14 +61,14 @@ class CFX_UTF8Encoder { } // namespace -CFX_ByteString FX_UTF8Encode(const CFX_WideStringC& wsStr) { +ByteString FX_UTF8Encode(const WideStringView& wsStr) { FX_STRSIZE len = wsStr.GetLength(); const wchar_t* pStr = wsStr.unterminated_c_str(); CFX_UTF8Encoder encoder; while (len-- > 0) encoder.Input(*pStr++); - return CFX_ByteString(encoder.GetResult()); + return ByteString(encoder.GetResult()); } namespace { @@ -84,7 +84,7 @@ float FractionalScale(size_t scale_factor, int value) { } // namespace -bool FX_atonum(const CFX_ByteStringC& strc, void* pData) { +bool FX_atonum(const ByteStringView& strc, void* pData) { if (strc.Contains('.')) { float* pFloat = static_cast(pData); *pFloat = FX_atof(strc); @@ -141,7 +141,7 @@ bool FX_atonum(const CFX_ByteStringC& strc, void* pData) { return true; } -float FX_atof(const CFX_ByteStringC& strc) { +float FX_atof(const ByteStringView& strc) { if (strc.IsEmpty()) return 0.0; @@ -180,7 +180,7 @@ float FX_atof(const CFX_ByteStringC& strc) { return bNegative ? -value : value; } -float FX_atof(const CFX_WideStringC& wsStr) { +float FX_atof(const WideStringView& wsStr) { return FX_atof(FX_UTF8Encode(wsStr).c_str()); } diff --git a/core/fxcrt/fx_string.h b/core/fxcrt/fx_string.h index 9cc0b251eb..0481a15d34 100644 --- a/core/fxcrt/fx_string.h +++ b/core/fxcrt/fx_string.h @@ -7,17 +7,17 @@ #ifndef CORE_FXCRT_FX_STRING_H_ #define CORE_FXCRT_FX_STRING_H_ -#include "core/fxcrt/cfx_bytestring.h" -#include "core/fxcrt/cfx_widestring.h" +#include "core/fxcrt/bytestring.h" +#include "core/fxcrt/widestring.h" #define FXBSTR_ID(c1, c2, c3, c4) \ (((uint32_t)c1 << 24) | ((uint32_t)c2 << 16) | ((uint32_t)c3 << 8) | \ ((uint32_t)c4)) -CFX_ByteString FX_UTF8Encode(const CFX_WideStringC& wsStr); -float FX_atof(const CFX_ByteStringC& str); -float FX_atof(const CFX_WideStringC& wsStr); -bool FX_atonum(const CFX_ByteStringC& str, void* pData); +ByteString FX_UTF8Encode(const WideStringView& wsStr); +float FX_atof(const ByteStringView& str); +float FX_atof(const WideStringView& wsStr); +bool FX_atonum(const ByteStringView& str, void* pData); FX_STRSIZE FX_ftoa(float f, char* buf); #endif // CORE_FXCRT_FX_STRING_H_ diff --git a/core/fxcrt/ifx_fileaccess.h b/core/fxcrt/ifx_fileaccess.h index e818303d85..9bfe2b4e63 100644 --- a/core/fxcrt/ifx_fileaccess.h +++ b/core/fxcrt/ifx_fileaccess.h @@ -19,8 +19,8 @@ class IFX_FileAccess { static std::unique_ptr Create(); virtual ~IFX_FileAccess() {} - virtual bool Open(const CFX_ByteStringC& fileName, uint32_t dwMode) = 0; - virtual bool Open(const CFX_WideStringC& fileName, uint32_t dwMode) = 0; + virtual bool Open(const ByteStringView& fileName, uint32_t dwMode) = 0; + virtual bool Open(const WideStringView& fileName, uint32_t dwMode) = 0; virtual void Close() = 0; virtual FX_FILESIZE GetSize() const = 0; virtual FX_FILESIZE GetPosition() const = 0; diff --git a/core/fxcrt/ifx_locale.h b/core/fxcrt/ifx_locale.h index 5039aec6f0..5918e7a183 100644 --- a/core/fxcrt/ifx_locale.h +++ b/core/fxcrt/ifx_locale.h @@ -58,19 +58,19 @@ class IFX_Locale { public: virtual ~IFX_Locale() {} - virtual CFX_WideString GetName() const = 0; - virtual CFX_WideString GetNumbericSymbol(FX_LOCALENUMSYMBOL eType) const = 0; - virtual CFX_WideString GetDateTimeSymbols() const = 0; - virtual CFX_WideString GetMonthName(int32_t nMonth, bool bAbbr) const = 0; - virtual CFX_WideString GetDayName(int32_t nWeek, bool bAbbr) const = 0; - virtual CFX_WideString GetMeridiemName(bool bAM) const = 0; + virtual WideString GetName() const = 0; + virtual WideString GetNumbericSymbol(FX_LOCALENUMSYMBOL eType) const = 0; + virtual WideString GetDateTimeSymbols() const = 0; + virtual WideString GetMonthName(int32_t nMonth, bool bAbbr) const = 0; + virtual WideString GetDayName(int32_t nWeek, bool bAbbr) const = 0; + virtual WideString GetMeridiemName(bool bAM) const = 0; virtual FX_TIMEZONE GetTimeZone() const = 0; - virtual CFX_WideString GetEraName(bool bAD) const = 0; - virtual CFX_WideString GetDatePattern( + virtual WideString GetEraName(bool bAD) const = 0; + virtual WideString GetDatePattern( FX_LOCALEDATETIMESUBCATEGORY eType) const = 0; - virtual CFX_WideString GetTimePattern( + virtual WideString GetTimePattern( FX_LOCALEDATETIMESUBCATEGORY eType) const = 0; - virtual CFX_WideString GetNumPattern(FX_LOCALENUMSUBCATEGORY eType) const = 0; + virtual WideString GetNumPattern(FX_LOCALENUMSUBCATEGORY eType) const = 0; }; #endif // CORE_FXCRT_IFX_LOCALE_H_ diff --git a/core/fxcrt/string_view_template.h b/core/fxcrt/string_view_template.h new file mode 100644 index 0000000000..21426acaeb --- /dev/null +++ b/core/fxcrt/string_view_template.h @@ -0,0 +1,247 @@ +// Copyright 2016 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef CORE_FXCRT_STRING_VIEW_TEMPLATE_H_ +#define CORE_FXCRT_STRING_VIEW_TEMPLATE_H_ + +#include +#include +#include +#include +#include + +#include "core/fxcrt/cfx_unowned_ptr.h" +#include "core/fxcrt/fx_system.h" +#include "third_party/base/optional.h" +#include "third_party/base/stl_util.h" + +namespace fxcrt { + +// An immutable string with caller-provided storage which must outlive the +// string itself. These are not necessarily nul-terminated, so that substring +// extraction (via the Mid(), Left(), and Right() methods) is copy-free. +template +class StringViewTemplate { + public: + using CharType = T; + using UnsignedType = typename std::make_unsigned::type; + using const_iterator = const CharType*; + using const_reverse_iterator = std::reverse_iterator; + + StringViewTemplate() : m_Ptr(nullptr), m_Length(0) {} + + // Deliberately implicit to avoid calling on every string literal. + // NOLINTNEXTLINE(runtime/explicit) + StringViewTemplate(const CharType* ptr) + : m_Ptr(reinterpret_cast(ptr)), + m_Length(ptr ? FXSYS_len(ptr) : 0) {} + + StringViewTemplate(const CharType* ptr, FX_STRSIZE len) + : m_Ptr(reinterpret_cast(ptr)), m_Length(len) {} + + template + StringViewTemplate( + const UnsignedType* ptr, + FX_STRSIZE size, + typename std::enable_if::value>::type* = 0) + : m_Ptr(ptr), m_Length(size) {} + + // Deliberately implicit to avoid calling on every string literal. + // |ch| must be an lvalue that outlives the the StringViewTemplate. + // NOLINTNEXTLINE(runtime/explicit) + StringViewTemplate(CharType& ch) { + m_Ptr = reinterpret_cast(&ch); + m_Length = 1; + } + + StringViewTemplate(const StringViewTemplate& src) { + m_Ptr = src.m_Ptr; + m_Length = src.m_Length; + } + + // Any changes to |vec| invalidate the string. + explicit StringViewTemplate(const std::vector& vec) { + m_Length = pdfium::CollectionSize(vec); + m_Ptr = m_Length ? vec.data() : nullptr; + } + + StringViewTemplate& operator=(const CharType* src) { + m_Ptr = reinterpret_cast(src); + m_Length = src ? FXSYS_len(src) : 0; + return *this; + } + + StringViewTemplate& operator=(const StringViewTemplate& src) { + m_Ptr = src.m_Ptr; + m_Length = src.m_Length; + return *this; + } + + const_iterator begin() const { + return reinterpret_cast(m_Ptr.Get()); + } + const_iterator end() const { + return m_Ptr ? reinterpret_cast(m_Ptr.Get()) + m_Length + : nullptr; + } + + const_reverse_iterator rbegin() const { + return const_reverse_iterator(end()); + } + const_reverse_iterator rend() const { + return const_reverse_iterator(begin()); + } + + bool operator==(const CharType* ptr) const { + return FXSYS_len(ptr) == m_Length && + FXSYS_cmp(ptr, reinterpret_cast(m_Ptr.Get()), + m_Length) == 0; + } + bool operator==(const StringViewTemplate& other) const { + return other.m_Length == m_Length && + FXSYS_cmp(reinterpret_cast(other.m_Ptr.Get()), + reinterpret_cast(m_Ptr.Get()), + m_Length) == 0; + } + bool operator!=(const CharType* ptr) const { return !(*this == ptr); } + bool operator!=(const StringViewTemplate& other) const { + return !(*this == other); + } + + uint32_t GetID() const { + if (m_Length == 0) + return 0; + + uint32_t strid = 0; + FX_STRSIZE size = std::min(static_cast(4), m_Length); + for (FX_STRSIZE i = 0; i < size; i++) + strid = strid * 256 + m_Ptr.Get()[i]; + + return strid << ((4 - size) * 8); + } + + const UnsignedType* raw_str() const { return m_Ptr.Get(); } + const CharType* unterminated_c_str() const { + return reinterpret_cast(m_Ptr.Get()); + } + + FX_STRSIZE GetLength() const { return m_Length; } + bool IsEmpty() const { return m_Length == 0; } + bool IsValidIndex(FX_STRSIZE index) const { return index < GetLength(); } + bool IsValidLength(FX_STRSIZE length) const { return length <= GetLength(); } + + const UnsignedType& operator[](const FX_STRSIZE index) const { + ASSERT(IsValidIndex(index)); + return m_Ptr.Get()[index]; + } + + UnsignedType First() const { return GetLength() ? (*this)[0] : 0; } + + UnsignedType Last() const { + return GetLength() ? (*this)[GetLength() - 1] : 0; + } + + const CharType CharAt(const FX_STRSIZE index) const { + ASSERT(IsValidIndex(index)); + return static_cast(m_Ptr.Get()[index]); + } + + pdfium::Optional Find(CharType ch) const { + const UnsignedType* found = reinterpret_cast(FXSYS_chr( + reinterpret_cast(m_Ptr.Get()), ch, m_Length)); + + return found ? pdfium::Optional(found - m_Ptr.Get()) + : pdfium::Optional(); + } + + bool Contains(CharType ch) const { return Find(ch).has_value(); } + + StringViewTemplate Mid(FX_STRSIZE first, FX_STRSIZE count) const { + if (!m_Ptr.Get()) + return StringViewTemplate(); + + if (!IsValidIndex(first)) + return StringViewTemplate(); + + if (count == 0 || !IsValidLength(count)) + return StringViewTemplate(); + + if (!IsValidIndex(first + count - 1)) + return StringViewTemplate(); + + return StringViewTemplate(m_Ptr.Get() + first, count); + } + + StringViewTemplate Left(FX_STRSIZE count) const { + if (count == 0 || !IsValidLength(count)) + return StringViewTemplate(); + return Mid(0, count); + } + + StringViewTemplate Right(FX_STRSIZE count) const { + if (count == 0 || !IsValidLength(count)) + return StringViewTemplate(); + return Mid(GetLength() - count, count); + } + + StringViewTemplate TrimmedRight(CharType ch) const { + if (IsEmpty()) + return StringViewTemplate(); + + FX_STRSIZE pos = GetLength(); + while (pos && CharAt(pos - 1) == ch) + pos--; + + if (pos == 0) + return StringViewTemplate(); + + return StringViewTemplate(m_Ptr.Get(), pos); + } + + bool operator<(const StringViewTemplate& that) const { + int result = FXSYS_cmp(reinterpret_cast(m_Ptr.Get()), + reinterpret_cast(that.m_Ptr.Get()), + std::min(m_Length, that.m_Length)); + return result < 0 || (result == 0 && m_Length < that.m_Length); + } + + bool operator>(const StringViewTemplate& that) const { + int result = FXSYS_cmp(reinterpret_cast(m_Ptr.Get()), + reinterpret_cast(that.m_Ptr.Get()), + std::min(m_Length, that.m_Length)); + return result > 0 || (result == 0 && m_Length > that.m_Length); + } + + protected: + CFX_UnownedPtr m_Ptr; + FX_STRSIZE m_Length; + + private: + void* operator new(size_t) throw() { return nullptr; } +}; + +template +inline bool operator==(const T* lhs, const StringViewTemplate& rhs) { + return rhs == lhs; +} + +template +inline bool operator!=(const T* lhs, const StringViewTemplate& rhs) { + return rhs != lhs; +} + +extern template class StringViewTemplate; +extern template class StringViewTemplate; + +using ByteStringView = StringViewTemplate; +using WideStringView = StringViewTemplate; + +} // namespace fxcrt + +using ByteStringView = fxcrt::ByteStringView; +using WideStringView = fxcrt::WideStringView; + +#endif // CORE_FXCRT_STRING_VIEW_TEMPLATE_H_ diff --git a/core/fxcrt/widestring.cpp b/core/fxcrt/widestring.cpp new file mode 100644 index 0000000000..fa5c80130d --- /dev/null +++ b/core/fxcrt/widestring.cpp @@ -0,0 +1,1054 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "core/fxcrt/widestring.h" + +#include + +#include +#include +#include + +#include "core/fxcrt/cfx_string_pool_template.h" +#include "core/fxcrt/cfx_utf8decoder.h" +#include "core/fxcrt/fx_codepage.h" +#include "core/fxcrt/fx_extension.h" +#include "core/fxcrt/fx_safe_types.h" +#include "third_party/base/numerics/safe_math.h" +#include "third_party/base/stl_util.h" + +template class CFX_StringDataTemplate; +template class fxcrt::StringViewTemplate; +template class CFX_StringPoolTemplate; +template struct std::hash; + +#define FORCE_ANSI 0x10000 +#define FORCE_UNICODE 0x20000 +#define FORCE_INT64 0x40000 + +namespace { + +const wchar_t* FX_wcsstr(const wchar_t* haystack, + int haystack_len, + const wchar_t* needle, + int needle_len) { + if (needle_len > haystack_len || needle_len == 0) { + return nullptr; + } + const wchar_t* end_ptr = haystack + haystack_len - needle_len; + while (haystack <= end_ptr) { + int i = 0; + while (1) { + if (haystack[i] != needle[i]) { + break; + } + i++; + if (i == needle_len) { + return haystack; + } + } + haystack++; + } + return nullptr; +} + +pdfium::Optional GuessSizeForVSWPrintf(const wchar_t* pFormat, + va_list argList) { + FX_STRSIZE nMaxLen = 0; + for (const wchar_t* pStr = pFormat; *pStr != 0; pStr++) { + if (*pStr != '%' || *(pStr = pStr + 1) == '%') { + ++nMaxLen; + continue; + } + int nItemLen = 0; + int nWidth = 0; + for (; *pStr != 0; pStr++) { + if (*pStr == '#') { + nMaxLen += 2; + } else if (*pStr == '*') { + nWidth = va_arg(argList, int); + } else if (*pStr != '-' && *pStr != '+' && *pStr != '0' && *pStr != ' ') { + break; + } + } + if (nWidth == 0) { + nWidth = FXSYS_wtoi(pStr); + while (std::iswdigit(*pStr)) + ++pStr; + } + if (nWidth < 0 || nWidth > 128 * 1024) + return pdfium::Optional(); + int nPrecision = 0; + if (*pStr == '.') { + pStr++; + if (*pStr == '*') { + nPrecision = va_arg(argList, int); + pStr++; + } else { + nPrecision = FXSYS_wtoi(pStr); + while (std::iswdigit(*pStr)) + ++pStr; + } + } + if (nPrecision < 0 || nPrecision > 128 * 1024) + return pdfium::Optional(); + int nModifier = 0; + if (*pStr == L'I' && *(pStr + 1) == L'6' && *(pStr + 2) == L'4') { + pStr += 3; + nModifier = FORCE_INT64; + } else { + switch (*pStr) { + case 'h': + nModifier = FORCE_ANSI; + pStr++; + break; + case 'l': + nModifier = FORCE_UNICODE; + pStr++; + break; + case 'F': + case 'N': + case 'L': + pStr++; + break; + } + } + switch (*pStr | nModifier) { + case 'c': + case 'C': + nItemLen = 2; + va_arg(argList, int); + break; + case 'c' | FORCE_ANSI: + case 'C' | FORCE_ANSI: + nItemLen = 2; + va_arg(argList, int); + break; + case 'c' | FORCE_UNICODE: + case 'C' | FORCE_UNICODE: + nItemLen = 2; + va_arg(argList, int); + break; + case 's': { + const wchar_t* pstrNextArg = va_arg(argList, const wchar_t*); + if (pstrNextArg) { + nItemLen = FXSYS_wcslen(pstrNextArg); + if (nItemLen < 1) { + nItemLen = 1; + } + } else { + nItemLen = 6; + } + } break; + case 'S': { + const char* pstrNextArg = va_arg(argList, const char*); + if (pstrNextArg) { + nItemLen = FXSYS_strlen(pstrNextArg); + if (nItemLen < 1) { + nItemLen = 1; + } + } else { + nItemLen = 6; + } + } break; + case 's' | FORCE_ANSI: + case 'S' | FORCE_ANSI: { + const char* pstrNextArg = va_arg(argList, const char*); + if (pstrNextArg) { + nItemLen = FXSYS_strlen(pstrNextArg); + if (nItemLen < 1) { + nItemLen = 1; + } + } else { + nItemLen = 6; + } + } break; + case 's' | FORCE_UNICODE: + case 'S' | FORCE_UNICODE: { + const wchar_t* pstrNextArg = va_arg(argList, wchar_t*); + if (pstrNextArg) { + nItemLen = FXSYS_wcslen(pstrNextArg); + if (nItemLen < 1) { + nItemLen = 1; + } + } else { + nItemLen = 6; + } + } break; + } + if (nItemLen != 0) { + if (nPrecision != 0 && nItemLen > nPrecision) { + nItemLen = nPrecision; + } + if (nItemLen < nWidth) { + nItemLen = nWidth; + } + } else { + switch (*pStr) { + case 'd': + case 'i': + case 'u': + case 'x': + case 'X': + case 'o': + if (nModifier & FORCE_INT64) { + va_arg(argList, int64_t); + } else { + va_arg(argList, int); + } + nItemLen = 32; + if (nItemLen < nWidth + nPrecision) { + nItemLen = nWidth + nPrecision; + } + break; + case 'a': + case 'A': + case 'e': + case 'E': + case 'g': + case 'G': + va_arg(argList, double); + nItemLen = 128; + if (nItemLen < nWidth + nPrecision) { + nItemLen = nWidth + nPrecision; + } + break; + case 'f': + if (nWidth + nPrecision > 100) { + nItemLen = nPrecision + nWidth + 128; + } else { + double f; + char pszTemp[256]; + f = va_arg(argList, double); + FXSYS_snprintf(pszTemp, sizeof(pszTemp), "%*.*f", nWidth, + nPrecision + 6, f); + nItemLen = FXSYS_strlen(pszTemp); + } + break; + case 'p': + va_arg(argList, void*); + nItemLen = 32; + if (nItemLen < nWidth + nPrecision) { + nItemLen = nWidth + nPrecision; + } + break; + case 'n': + va_arg(argList, int*); + break; + } + } + nMaxLen += nItemLen; + } + nMaxLen += 32; // Fudge factor. + return pdfium::Optional(nMaxLen); +} + +#ifndef NDEBUG +bool IsValidCodePage(uint16_t codepage) { + switch (codepage) { + case FX_CODEPAGE_DefANSI: + case FX_CODEPAGE_ShiftJIS: + case FX_CODEPAGE_ChineseSimplified: + case FX_CODEPAGE_Hangul: + case FX_CODEPAGE_ChineseTraditional: + return true; + default: + return false; + } +} +#endif + +WideString GetWideString(uint16_t codepage, const ByteStringView& bstr) { + ASSERT(IsValidCodePage(codepage)); + + int src_len = bstr.GetLength(); + int dest_len = FXSYS_MultiByteToWideChar( + codepage, 0, bstr.unterminated_c_str(), src_len, nullptr, 0); + if (!dest_len) + return WideString(); + + WideString wstr; + wchar_t* dest_buf = wstr.GetBuffer(dest_len); + FXSYS_MultiByteToWideChar(codepage, 0, bstr.unterminated_c_str(), src_len, + dest_buf, dest_len); + wstr.ReleaseBuffer(dest_len); + return wstr; +} + +} // namespace + +namespace fxcrt { + +static_assert(sizeof(WideString) <= sizeof(wchar_t*), + "Strings must not require more space than pointers"); + +WideString::WideString() {} + +WideString::WideString(const WideString& other) : m_pData(other.m_pData) {} + +WideString::WideString(WideString&& other) noexcept { + m_pData.Swap(other.m_pData); +} + +WideString::WideString(const wchar_t* pStr, FX_STRSIZE nLen) { + if (nLen) + m_pData.Reset(StringData::Create(pStr, nLen)); +} + +WideString::WideString(wchar_t ch) { + m_pData.Reset(StringData::Create(1)); + m_pData->m_String[0] = ch; +} + +WideString::WideString(const wchar_t* ptr) + : WideString(ptr, ptr ? FXSYS_wcslen(ptr) : 0) {} + +WideString::WideString(const WideStringView& stringSrc) { + if (!stringSrc.IsEmpty()) { + m_pData.Reset(StringData::Create(stringSrc.unterminated_c_str(), + stringSrc.GetLength())); + } +} + +WideString::WideString(const WideStringView& str1, const WideStringView& str2) { + FX_SAFE_STRSIZE nSafeLen = str1.GetLength(); + nSafeLen += str2.GetLength(); + + FX_STRSIZE nNewLen = nSafeLen.ValueOrDie(); + if (nNewLen == 0) + return; + + m_pData.Reset(StringData::Create(nNewLen)); + m_pData->CopyContents(str1.unterminated_c_str(), str1.GetLength()); + m_pData->CopyContentsAt(str1.GetLength(), str2.unterminated_c_str(), + str2.GetLength()); +} + +WideString::WideString(const std::initializer_list& list) { + FX_SAFE_STRSIZE nSafeLen = 0; + for (const auto& item : list) + nSafeLen += item.GetLength(); + + FX_STRSIZE nNewLen = nSafeLen.ValueOrDie(); + if (nNewLen == 0) + return; + + m_pData.Reset(StringData::Create(nNewLen)); + + FX_STRSIZE nOffset = 0; + for (const auto& item : list) { + m_pData->CopyContentsAt(nOffset, item.unterminated_c_str(), + item.GetLength()); + nOffset += item.GetLength(); + } +} + +WideString::~WideString() {} + +const WideString& WideString::operator=(const wchar_t* pStr) { + if (!pStr || !pStr[0]) + clear(); + else + AssignCopy(pStr, FXSYS_wcslen(pStr)); + + return *this; +} + +const WideString& WideString::operator=(const WideStringView& stringSrc) { + if (stringSrc.IsEmpty()) + clear(); + else + AssignCopy(stringSrc.unterminated_c_str(), stringSrc.GetLength()); + + return *this; +} + +const WideString& WideString::operator=(const WideString& stringSrc) { + if (m_pData != stringSrc.m_pData) + m_pData = stringSrc.m_pData; + + return *this; +} + +const WideString& WideString::operator+=(const wchar_t* pStr) { + if (pStr) + Concat(pStr, FXSYS_wcslen(pStr)); + + return *this; +} + +const WideString& WideString::operator+=(wchar_t ch) { + Concat(&ch, 1); + return *this; +} + +const WideString& WideString::operator+=(const WideString& str) { + if (str.m_pData) + Concat(str.m_pData->m_String, str.m_pData->m_nDataLength); + + return *this; +} + +const WideString& WideString::operator+=(const WideStringView& str) { + if (!str.IsEmpty()) + Concat(str.unterminated_c_str(), str.GetLength()); + + return *this; +} + +bool WideString::operator==(const wchar_t* ptr) const { + if (!m_pData) + return !ptr || !ptr[0]; + + if (!ptr) + return m_pData->m_nDataLength == 0; + + return wcslen(ptr) == m_pData->m_nDataLength && + wmemcmp(ptr, m_pData->m_String, m_pData->m_nDataLength) == 0; +} + +bool WideString::operator==(const WideStringView& str) const { + if (!m_pData) + return str.IsEmpty(); + + return m_pData->m_nDataLength == str.GetLength() && + wmemcmp(m_pData->m_String, str.unterminated_c_str(), + str.GetLength()) == 0; +} + +bool WideString::operator==(const WideString& other) const { + if (m_pData == other.m_pData) + return true; + + if (IsEmpty()) + return other.IsEmpty(); + + if (other.IsEmpty()) + return false; + + return other.m_pData->m_nDataLength == m_pData->m_nDataLength && + wmemcmp(other.m_pData->m_String, m_pData->m_String, + m_pData->m_nDataLength) == 0; +} + +bool WideString::operator<(const WideString& str) const { + if (m_pData == str.m_pData) + return false; + + int result = + wmemcmp(c_str(), str.c_str(), std::min(GetLength(), str.GetLength())); + return result < 0 || (result == 0 && GetLength() < str.GetLength()); +} + +void WideString::AssignCopy(const wchar_t* pSrcData, FX_STRSIZE nSrcLen) { + AllocBeforeWrite(nSrcLen); + m_pData->CopyContents(pSrcData, nSrcLen); + m_pData->m_nDataLength = nSrcLen; +} + +void WideString::ReallocBeforeWrite(FX_STRSIZE nNewLength) { + if (m_pData && m_pData->CanOperateInPlace(nNewLength)) + return; + + if (nNewLength == 0) { + clear(); + return; + } + + CFX_RetainPtr pNewData(StringData::Create(nNewLength)); + if (m_pData) { + FX_STRSIZE nCopyLength = std::min(m_pData->m_nDataLength, nNewLength); + pNewData->CopyContents(m_pData->m_String, nCopyLength); + pNewData->m_nDataLength = nCopyLength; + } else { + pNewData->m_nDataLength = 0; + } + pNewData->m_String[pNewData->m_nDataLength] = 0; + m_pData.Swap(pNewData); +} + +void WideString::AllocBeforeWrite(FX_STRSIZE nNewLength) { + if (m_pData && m_pData->CanOperateInPlace(nNewLength)) + return; + + if (nNewLength == 0) { + clear(); + return; + } + + m_pData.Reset(StringData::Create(nNewLength)); +} + +void WideString::ReleaseBuffer(FX_STRSIZE nNewLength) { + if (!m_pData) + return; + + nNewLength = std::min(nNewLength, m_pData->m_nAllocLength); + if (nNewLength == 0) { + clear(); + return; + } + + ASSERT(m_pData->m_nRefs == 1); + m_pData->m_nDataLength = nNewLength; + m_pData->m_String[nNewLength] = 0; + if (m_pData->m_nAllocLength - nNewLength >= 32) { + // Over arbitrary threshold, so pay the price to relocate. Force copy to + // always occur by holding a second reference to the string. + WideString preserve(*this); + ReallocBeforeWrite(nNewLength); + } +} + +void WideString::Reserve(FX_STRSIZE len) { + GetBuffer(len); +} + +wchar_t* WideString::GetBuffer(FX_STRSIZE nMinBufLength) { + if (!m_pData) { + if (nMinBufLength == 0) + return nullptr; + + m_pData.Reset(StringData::Create(nMinBufLength)); + m_pData->m_nDataLength = 0; + m_pData->m_String[0] = 0; + return m_pData->m_String; + } + + if (m_pData->CanOperateInPlace(nMinBufLength)) + return m_pData->m_String; + + nMinBufLength = std::max(nMinBufLength, m_pData->m_nDataLength); + if (nMinBufLength == 0) + return nullptr; + + CFX_RetainPtr pNewData(StringData::Create(nMinBufLength)); + pNewData->CopyContents(*m_pData); + pNewData->m_nDataLength = m_pData->m_nDataLength; + m_pData.Swap(pNewData); + return m_pData->m_String; +} + +FX_STRSIZE WideString::Delete(FX_STRSIZE index, FX_STRSIZE count) { + if (!m_pData) + return 0; + + FX_STRSIZE old_length = m_pData->m_nDataLength; + if (count == 0 || + index != pdfium::clamp(index, static_cast(0), old_length)) + return old_length; + + FX_STRSIZE removal_length = index + count; + if (removal_length > old_length) + return old_length; + + ReallocBeforeWrite(old_length); + FX_STRSIZE chars_to_copy = old_length - removal_length + 1; + wmemmove(m_pData->m_String + index, m_pData->m_String + removal_length, + chars_to_copy); + m_pData->m_nDataLength = old_length - count; + return m_pData->m_nDataLength; +} + +void WideString::Concat(const wchar_t* pSrcData, FX_STRSIZE nSrcLen) { + if (!pSrcData || nSrcLen == 0) + return; + + if (!m_pData) { + m_pData.Reset(StringData::Create(pSrcData, nSrcLen)); + return; + } + + if (m_pData->CanOperateInPlace(m_pData->m_nDataLength + nSrcLen)) { + m_pData->CopyContentsAt(m_pData->m_nDataLength, pSrcData, nSrcLen); + m_pData->m_nDataLength += nSrcLen; + return; + } + + CFX_RetainPtr pNewData( + StringData::Create(m_pData->m_nDataLength + nSrcLen)); + pNewData->CopyContents(*m_pData); + pNewData->CopyContentsAt(m_pData->m_nDataLength, pSrcData, nSrcLen); + m_pData.Swap(pNewData); +} + +ByteString WideString::UTF8Encode() const { + return FX_UTF8Encode(AsStringView()); +} + +ByteString WideString::UTF16LE_Encode() const { + if (!m_pData) { + return ByteString("\0\0", 2); + } + int len = m_pData->m_nDataLength; + ByteString result; + char* buffer = result.GetBuffer(len * 2 + 2); + for (int i = 0; i < len; i++) { + buffer[i * 2] = m_pData->m_String[i] & 0xff; + buffer[i * 2 + 1] = m_pData->m_String[i] >> 8; + } + buffer[len * 2] = 0; + buffer[len * 2 + 1] = 0; + result.ReleaseBuffer(len * 2 + 2); + return result; +} + +WideString WideString::Mid(FX_STRSIZE first, FX_STRSIZE count) const { + if (!m_pData) + return WideString(); + + if (!IsValidIndex(first)) + return WideString(); + + if (count == 0 || !IsValidLength(count)) + return WideString(); + + if (!IsValidIndex(first + count - 1)) + return WideString(); + + if (first == 0 && count == GetLength()) + return *this; + + WideString dest; + AllocCopy(dest, count, first); + return dest; +} + +WideString WideString::Left(FX_STRSIZE count) const { + if (count == 0 || !IsValidLength(count)) + return WideString(); + return Mid(0, count); +} + +WideString WideString::Right(FX_STRSIZE count) const { + if (count == 0 || !IsValidLength(count)) + return WideString(); + return Mid(GetLength() - count, count); +} + +void WideString::AllocCopy(WideString& dest, + FX_STRSIZE nCopyLen, + FX_STRSIZE nCopyIndex) const { + if (nCopyLen == 0) + return; + + CFX_RetainPtr pNewData( + StringData::Create(m_pData->m_String + nCopyIndex, nCopyLen)); + dest.m_pData.Swap(pNewData); +} + +bool WideString::TryVSWPrintf(FX_STRSIZE size, + const wchar_t* pFormat, + va_list argList) { + GetBuffer(size); + if (!m_pData) + return true; + + // In the following two calls, there's always space in the buffer for + // a terminating NUL that's not included in nMaxLen. + // For vswprintf(), MSAN won't untaint the buffer on a truncated write's + // -1 return code even though the buffer is written. Probably just as well + // not to trust the vendor's implementation to write anything anyways. + // See https://crbug.com/705912. + memset(m_pData->m_String, 0, (size + 1) * sizeof(wchar_t)); + int ret = vswprintf(m_pData->m_String, size + 1, pFormat, argList); + bool bSufficientBuffer = ret >= 0 || m_pData->m_String[size - 1] == 0; + ReleaseBuffer(GetStringLength()); + return bSufficientBuffer; +} + +void WideString::FormatV(const wchar_t* format, va_list argList) { + va_list argListCopy; + va_copy(argListCopy, argList); + int maxLen = vswprintf(nullptr, 0, format, argListCopy); + va_end(argListCopy); + if (maxLen <= 0) { + va_copy(argListCopy, argList); + auto guess = GuessSizeForVSWPrintf(format, argListCopy); + va_end(argListCopy); + if (!guess.has_value()) + return; + maxLen = pdfium::base::checked_cast(guess.value()); + } + while (maxLen < 32 * 1024) { + va_copy(argListCopy, argList); + bool bSufficientBuffer = + TryVSWPrintf(static_cast(maxLen), format, argListCopy); + va_end(argListCopy); + if (bSufficientBuffer) + break; + maxLen *= 2; + } +} + +void WideString::Format(const wchar_t* pFormat, ...) { + va_list argList; + va_start(argList, pFormat); + FormatV(pFormat, argList); + va_end(argList); +} + +FX_STRSIZE WideString::Insert(FX_STRSIZE location, wchar_t ch) { + const FX_STRSIZE cur_length = m_pData ? m_pData->m_nDataLength : 0; + if (!IsValidLength(location)) + return cur_length; + + const FX_STRSIZE new_length = cur_length + 1; + ReallocBeforeWrite(new_length); + wmemmove(m_pData->m_String + location + 1, m_pData->m_String + location, + new_length - location); + m_pData->m_String[location] = ch; + m_pData->m_nDataLength = new_length; + return new_length; +} + +pdfium::Optional WideString::Find(wchar_t ch, + FX_STRSIZE start) const { + if (!m_pData) + return pdfium::Optional(); + + if (!IsValidIndex(start)) + return pdfium::Optional(); + + const wchar_t* pStr = + wmemchr(m_pData->m_String + start, ch, m_pData->m_nDataLength - start); + return pStr ? pdfium::Optional( + static_cast(pStr - m_pData->m_String)) + : pdfium::Optional(); +} + +pdfium::Optional WideString::Find(const WideStringView& subStr, + FX_STRSIZE start) const { + if (!m_pData) + return pdfium::Optional(); + + if (!IsValidIndex(start)) + return pdfium::Optional(); + + const wchar_t* pStr = + FX_wcsstr(m_pData->m_String + start, m_pData->m_nDataLength - start, + subStr.unterminated_c_str(), subStr.GetLength()); + return pStr ? pdfium::Optional( + static_cast(pStr - m_pData->m_String)) + : pdfium::Optional(); +} + +void WideString::MakeLower() { + if (!m_pData) + return; + + ReallocBeforeWrite(m_pData->m_nDataLength); + FXSYS_wcslwr(m_pData->m_String); +} + +void WideString::MakeUpper() { + if (!m_pData) + return; + + ReallocBeforeWrite(m_pData->m_nDataLength); + FXSYS_wcsupr(m_pData->m_String); +} + +FX_STRSIZE WideString::Remove(wchar_t chRemove) { + if (!m_pData || m_pData->m_nDataLength < 1) + return 0; + + wchar_t* pstrSource = m_pData->m_String; + wchar_t* pstrEnd = m_pData->m_String + m_pData->m_nDataLength; + while (pstrSource < pstrEnd) { + if (*pstrSource == chRemove) + break; + pstrSource++; + } + if (pstrSource == pstrEnd) + return 0; + + ptrdiff_t copied = pstrSource - m_pData->m_String; + ReallocBeforeWrite(m_pData->m_nDataLength); + pstrSource = m_pData->m_String + copied; + pstrEnd = m_pData->m_String + m_pData->m_nDataLength; + + wchar_t* pstrDest = pstrSource; + while (pstrSource < pstrEnd) { + if (*pstrSource != chRemove) { + *pstrDest = *pstrSource; + pstrDest++; + } + pstrSource++; + } + + *pstrDest = 0; + FX_STRSIZE count = static_cast(pstrSource - pstrDest); + m_pData->m_nDataLength -= count; + return count; +} + +FX_STRSIZE WideString::Replace(const WideStringView& pOld, + const WideStringView& pNew) { + if (!m_pData || pOld.IsEmpty()) + return 0; + + FX_STRSIZE nSourceLen = pOld.GetLength(); + FX_STRSIZE nReplacementLen = pNew.GetLength(); + FX_STRSIZE count = 0; + const wchar_t* pStart = m_pData->m_String; + wchar_t* pEnd = m_pData->m_String + m_pData->m_nDataLength; + while (1) { + const wchar_t* pTarget = FX_wcsstr(pStart, (FX_STRSIZE)(pEnd - pStart), + pOld.unterminated_c_str(), nSourceLen); + if (!pTarget) + break; + + count++; + pStart = pTarget + nSourceLen; + } + if (count == 0) + return 0; + + FX_STRSIZE nNewLength = + m_pData->m_nDataLength + (nReplacementLen - nSourceLen) * count; + + if (nNewLength == 0) { + clear(); + return count; + } + + CFX_RetainPtr pNewData(StringData::Create(nNewLength)); + pStart = m_pData->m_String; + wchar_t* pDest = pNewData->m_String; + for (FX_STRSIZE i = 0; i < count; i++) { + const wchar_t* pTarget = FX_wcsstr(pStart, (FX_STRSIZE)(pEnd - pStart), + pOld.unterminated_c_str(), nSourceLen); + wmemcpy(pDest, pStart, pTarget - pStart); + pDest += pTarget - pStart; + wmemcpy(pDest, pNew.unterminated_c_str(), pNew.GetLength()); + pDest += pNew.GetLength(); + pStart = pTarget + nSourceLen; + } + wmemcpy(pDest, pStart, pEnd - pStart); + m_pData.Swap(pNewData); + return count; +} + +// static +WideString WideString::FromLocal(const ByteStringView& str) { + return FromCodePage(str, 0); +} + +// static +WideString WideString::FromCodePage(const ByteStringView& str, + uint16_t codepage) { + return GetWideString(codepage, str); +} + +// static +WideString WideString::FromUTF8(const ByteStringView& str) { + if (str.IsEmpty()) + return WideString(); + + CFX_UTF8Decoder decoder; + for (FX_STRSIZE i = 0; i < str.GetLength(); i++) + decoder.Input(str[i]); + + return WideString(decoder.GetResult()); +} + +// static +WideString WideString::FromUTF16LE(const unsigned short* wstr, + FX_STRSIZE wlen) { + if (!wstr || wlen == 0) { + return WideString(); + } + + WideString result; + wchar_t* buf = result.GetBuffer(wlen); + for (FX_STRSIZE i = 0; i < wlen; i++) { + buf[i] = wstr[i]; + } + result.ReleaseBuffer(wlen); + return result; +} + +void WideString::SetAt(FX_STRSIZE index, wchar_t c) { + ASSERT(IsValidIndex(index)); + ReallocBeforeWrite(m_pData->m_nDataLength); + m_pData->m_String[index] = c; +} + +int WideString::Compare(const wchar_t* lpsz) const { + if (m_pData) + return wcscmp(m_pData->m_String, lpsz); + return (!lpsz || lpsz[0] == 0) ? 0 : -1; +} + +int WideString::Compare(const WideString& str) const { + if (!m_pData) { + if (!str.m_pData) { + return 0; + } + return -1; + } + if (!str.m_pData) { + return 1; + } + FX_STRSIZE this_len = m_pData->m_nDataLength; + FX_STRSIZE that_len = str.m_pData->m_nDataLength; + FX_STRSIZE min_len = std::min(this_len, that_len); + for (FX_STRSIZE i = 0; i < min_len; i++) { + if (m_pData->m_String[i] < str.m_pData->m_String[i]) { + return -1; + } + if (m_pData->m_String[i] > str.m_pData->m_String[i]) { + return 1; + } + } + if (this_len < that_len) { + return -1; + } + if (this_len > that_len) { + return 1; + } + return 0; +} + +int WideString::CompareNoCase(const wchar_t* lpsz) const { + if (!m_pData) { + return (!lpsz || lpsz[0] == 0) ? 0 : -1; + } + return FXSYS_wcsicmp(m_pData->m_String, lpsz); +} + +FX_STRSIZE WideString::WStringLength(const unsigned short* str) { + FX_STRSIZE len = 0; + if (str) + while (str[len]) + len++; + return len; +} + +void WideString::TrimRight(const WideStringView& pTargets) { + if (IsEmpty() || pTargets.IsEmpty()) + return; + + FX_STRSIZE pos = GetLength(); + while (pos && pTargets.Contains(m_pData->m_String[pos - 1])) + pos--; + + if (pos < m_pData->m_nDataLength) { + ReallocBeforeWrite(m_pData->m_nDataLength); + m_pData->m_String[pos] = 0; + m_pData->m_nDataLength = pos; + } +} + +void WideString::TrimRight(wchar_t chTarget) { + wchar_t str[2] = {chTarget, 0}; + TrimRight(str); +} + +void WideString::TrimRight() { + TrimRight(L"\x09\x0a\x0b\x0c\x0d\x20"); +} + +void WideString::TrimLeft(const WideStringView& pTargets) { + if (!m_pData || pTargets.IsEmpty()) + return; + + FX_STRSIZE len = GetLength(); + if (len == 0) + return; + + FX_STRSIZE pos = 0; + while (pos < len) { + FX_STRSIZE i = 0; + while (i < pTargets.GetLength() && + pTargets.CharAt(i) != m_pData->m_String[pos]) { + i++; + } + if (i == pTargets.GetLength()) { + break; + } + pos++; + } + if (!pos) + return; + + ReallocBeforeWrite(len); + FX_STRSIZE nDataLength = len - pos; + memmove(m_pData->m_String, m_pData->m_String + pos, + (nDataLength + 1) * sizeof(wchar_t)); + m_pData->m_nDataLength = nDataLength; +} + +void WideString::TrimLeft(wchar_t chTarget) { + wchar_t str[2] = {chTarget, 0}; + TrimLeft(str); +} + +void WideString::TrimLeft() { + TrimLeft(L"\x09\x0a\x0b\x0c\x0d\x20"); +} +float FX_wtof(const wchar_t* str, int len) { + if (len == 0) { + return 0.0; + } + int cc = 0; + bool bNegative = false; + if (str[0] == '+') { + cc++; + } else if (str[0] == '-') { + bNegative = true; + cc++; + } + int integer = 0; + while (cc < len) { + if (str[cc] == '.') { + break; + } + integer = integer * 10 + FXSYS_DecimalCharToInt(str[cc]); + cc++; + } + float fraction = 0; + if (str[cc] == '.') { + cc++; + float scale = 0.1f; + while (cc < len) { + fraction += scale * FXSYS_DecimalCharToInt(str[cc]); + scale *= 0.1f; + cc++; + } + } + fraction += static_cast(integer); + return bNegative ? -fraction : fraction; +} + +int WideString::GetInteger() const { + return m_pData ? FXSYS_wtoi(m_pData->m_String) : 0; +} + +float WideString::GetFloat() const { + return m_pData ? FX_wtof(m_pData->m_String, m_pData->m_nDataLength) : 0.0f; +} + +std::wostream& operator<<(std::wostream& os, const WideString& str) { + return os.write(str.c_str(), str.GetLength()); +} + +std::ostream& operator<<(std::ostream& os, const WideString& str) { + os << str.UTF8Encode(); + return os; +} + +std::wostream& operator<<(std::wostream& os, const WideStringView& str) { + return os.write(str.unterminated_c_str(), str.GetLength()); +} + +std::ostream& operator<<(std::ostream& os, const WideStringView& str) { + os << FX_UTF8Encode(str); + return os; +} + +} // namespace fxcrt diff --git a/core/fxcrt/widestring.h b/core/fxcrt/widestring.h new file mode 100644 index 0000000000..8841c84093 --- /dev/null +++ b/core/fxcrt/widestring.h @@ -0,0 +1,277 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef CORE_FXCRT_WIDESTRING_H_ +#define CORE_FXCRT_WIDESTRING_H_ + +#include +#include +#include + +#include "core/fxcrt/cfx_retain_ptr.h" +#include "core/fxcrt/cfx_string_data_template.h" +#include "core/fxcrt/fx_memory.h" +#include "core/fxcrt/fx_system.h" +#include "core/fxcrt/string_view_template.h" +#include "third_party/base/optional.h" + +class WideString_ConcatInPlace_Test; +class fxcrt_WideStringPool_Test; + +namespace fxcrt { + +class ByteString; + +// A mutable string with shared buffers using copy-on-write semantics that +// avoids the cost of std::string's iterator stability guarantees. +class WideString { + public: + using CharType = wchar_t; + using const_iterator = const CharType*; + using const_reverse_iterator = std::reverse_iterator; + + WideString(); + WideString(const WideString& other); + WideString(WideString&& other) noexcept; + + // Deliberately implicit to avoid calling on every string literal. + // NOLINTNEXTLINE(runtime/explicit) + WideString(wchar_t ch); + // NOLINTNEXTLINE(runtime/explicit) + WideString(const wchar_t* ptr); + + // No implicit conversions from byte strings. + // NOLINTNEXTLINE(runtime/explicit) + WideString(char) = delete; + + WideString(const wchar_t* ptr, FX_STRSIZE len); + + explicit WideString(const WideStringView& str); + WideString(const WideStringView& str1, const WideStringView& str2); + WideString(const std::initializer_list& list); + + ~WideString(); + + static WideString FromLocal(const ByteStringView& str); + static WideString FromCodePage(const ByteStringView& str, uint16_t codepage); + + static WideString FromUTF8(const ByteStringView& str); + static WideString FromUTF16LE(const unsigned short* str, FX_STRSIZE len); + + static FX_STRSIZE WStringLength(const unsigned short* str); + + // Explicit conversion to C-style wide string. + // Note: Any subsequent modification of |this| will invalidate the result. + const wchar_t* c_str() const { return m_pData ? m_pData->m_String : L""; } + + // Explicit conversion to WideStringView. + // Note: Any subsequent modification of |this| will invalidate the result. + WideStringView AsStringView() const { + return WideStringView(c_str(), GetLength()); + } + + // Note: Any subsequent modification of |this| will invalidate iterators. + const_iterator begin() const { return m_pData ? m_pData->m_String : nullptr; } + const_iterator end() const { + return m_pData ? m_pData->m_String + m_pData->m_nDataLength : nullptr; + } + + // Note: Any subsequent modification of |this| will invalidate iterators. + const_reverse_iterator rbegin() const { + return const_reverse_iterator(end()); + } + const_reverse_iterator rend() const { + return const_reverse_iterator(begin()); + } + + void clear() { m_pData.Reset(); } + + FX_STRSIZE GetLength() const { return m_pData ? m_pData->m_nDataLength : 0; } + FX_STRSIZE GetStringLength() const { + return m_pData ? FXSYS_wcslen(m_pData->m_String) : 0; + } + bool IsEmpty() const { return !GetLength(); } + bool IsValidIndex(FX_STRSIZE index) const { return index < GetLength(); } + bool IsValidLength(FX_STRSIZE length) const { return length <= GetLength(); } + + const WideString& operator=(const wchar_t* str); + const WideString& operator=(const WideString& stringSrc); + const WideString& operator=(const WideStringView& stringSrc); + + const WideString& operator+=(const wchar_t* str); + const WideString& operator+=(wchar_t ch); + const WideString& operator+=(const WideString& str); + const WideString& operator+=(const WideStringView& str); + + bool operator==(const wchar_t* ptr) const; + bool operator==(const WideStringView& str) const; + bool operator==(const WideString& other) const; + + bool operator!=(const wchar_t* ptr) const { return !(*this == ptr); } + bool operator!=(const WideStringView& str) const { return !(*this == str); } + bool operator!=(const WideString& other) const { return !(*this == other); } + + bool operator<(const WideString& str) const; + + CharType operator[](const FX_STRSIZE index) const { + ASSERT(IsValidIndex(index)); + return m_pData ? m_pData->m_String[index] : 0; + } + + CharType First() const { return GetLength() ? (*this)[0] : 0; } + CharType Last() const { return GetLength() ? (*this)[GetLength() - 1] : 0; } + + void SetAt(FX_STRSIZE index, wchar_t c); + + int Compare(const wchar_t* str) const; + int Compare(const WideString& str) const; + int CompareNoCase(const wchar_t* str) const; + + WideString Mid(FX_STRSIZE first, FX_STRSIZE count) const; + WideString Left(FX_STRSIZE count) const; + WideString Right(FX_STRSIZE count) const; + + FX_STRSIZE Insert(FX_STRSIZE index, wchar_t ch); + FX_STRSIZE InsertAtFront(wchar_t ch) { return Insert(0, ch); } + FX_STRSIZE InsertAtBack(wchar_t ch) { return Insert(GetLength(), ch); } + FX_STRSIZE Delete(FX_STRSIZE index, FX_STRSIZE count = 1); + + void Format(const wchar_t* lpszFormat, ...); + void FormatV(const wchar_t* lpszFormat, va_list argList); + + void MakeLower(); + void MakeUpper(); + + void TrimRight(); + void TrimRight(wchar_t chTarget); + void TrimRight(const WideStringView& pTargets); + + void TrimLeft(); + void TrimLeft(wchar_t chTarget); + void TrimLeft(const WideStringView& pTargets); + + void Reserve(FX_STRSIZE len); + wchar_t* GetBuffer(FX_STRSIZE len); + void ReleaseBuffer(FX_STRSIZE len); + + int GetInteger() const; + float GetFloat() const; + + pdfium::Optional Find(const WideStringView& pSub, + FX_STRSIZE start = 0) const; + pdfium::Optional Find(wchar_t ch, FX_STRSIZE start = 0) const; + + bool Contains(const WideStringView& lpszSub, FX_STRSIZE start = 0) const { + return Find(lpszSub, start).has_value(); + } + + bool Contains(char ch, FX_STRSIZE start = 0) const { + return Find(ch, start).has_value(); + } + + FX_STRSIZE Replace(const WideStringView& pOld, const WideStringView& pNew); + FX_STRSIZE Remove(wchar_t ch); + + ByteString UTF8Encode() const; + ByteString UTF16LE_Encode() const; + + protected: + using StringData = CFX_StringDataTemplate; + + void ReallocBeforeWrite(FX_STRSIZE nLen); + void AllocBeforeWrite(FX_STRSIZE nLen); + void AllocCopy(WideString& dest, + FX_STRSIZE nCopyLen, + FX_STRSIZE nCopyIndex) const; + void AssignCopy(const wchar_t* pSrcData, FX_STRSIZE nSrcLen); + void Concat(const wchar_t* lpszSrcData, FX_STRSIZE nSrcLen); + + // Returns true unless we ran out of space. + bool TryVSWPrintf(FX_STRSIZE size, const wchar_t* format, va_list argList); + + CFX_RetainPtr m_pData; + + friend WideString_ConcatInPlace_Test; + friend fxcrt_WideStringPool_Test; +}; + +inline WideString operator+(const WideStringView& str1, + const WideStringView& str2) { + return WideString(str1, str2); +} +inline WideString operator+(const WideStringView& str1, const wchar_t* str2) { + return WideString(str1, str2); +} +inline WideString operator+(const wchar_t* str1, const WideStringView& str2) { + return WideString(str1, str2); +} +inline WideString operator+(const WideStringView& str1, wchar_t ch) { + return WideString(str1, WideStringView(ch)); +} +inline WideString operator+(wchar_t ch, const WideStringView& str2) { + return WideString(ch, str2); +} +inline WideString operator+(const WideString& str1, const WideString& str2) { + return WideString(str1.AsStringView(), str2.AsStringView()); +} +inline WideString operator+(const WideString& str1, wchar_t ch) { + return WideString(str1.AsStringView(), WideStringView(ch)); +} +inline WideString operator+(wchar_t ch, const WideString& str2) { + return WideString(ch, str2.AsStringView()); +} +inline WideString operator+(const WideString& str1, const wchar_t* str2) { + return WideString(str1.AsStringView(), str2); +} +inline WideString operator+(const wchar_t* str1, const WideString& str2) { + return WideString(str1, str2.AsStringView()); +} +inline WideString operator+(const WideString& str1, + const WideStringView& str2) { + return WideString(str1.AsStringView(), str2); +} +inline WideString operator+(const WideStringView& str1, + const WideString& str2) { + return WideString(str1, str2.AsStringView()); +} +inline bool operator==(const wchar_t* lhs, const WideString& rhs) { + return rhs == lhs; +} +inline bool operator==(const WideStringView& lhs, const WideString& rhs) { + return rhs == lhs; +} +inline bool operator!=(const wchar_t* lhs, const WideString& rhs) { + return rhs != lhs; +} +inline bool operator!=(const WideStringView& lhs, const WideString& rhs) { + return rhs != lhs; +} + +std::wostream& operator<<(std::wostream& os, const WideString& str); +std::ostream& operator<<(std::ostream& os, const WideString& str); +std::wostream& operator<<(std::wostream& os, const WideStringView& str); +std::ostream& operator<<(std::ostream& os, const WideStringView& str); + +} // namespace fxcrt + +using WideString = fxcrt::WideString; + +uint32_t FX_HashCode_GetW(const WideStringView& str, bool bIgnoreCase); + +namespace std { + +template <> +struct hash { + std::size_t operator()(const WideString& str) const { + return FX_HashCode_GetW(str.AsStringView(), false); + } +}; + +} // namespace std + +extern template struct std::hash; + +#endif // CORE_FXCRT_WIDESTRING_H_ diff --git a/core/fxcrt/widestring_unittest.cpp b/core/fxcrt/widestring_unittest.cpp new file mode 100644 index 0000000000..949827f6f1 --- /dev/null +++ b/core/fxcrt/widestring_unittest.cpp @@ -0,0 +1,1605 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "core/fxcrt/widestring.h" + +#include +#include + +#include "core/fxcrt/fx_string.h" +#include "testing/gtest/include/gtest/gtest.h" + +TEST(WideString, ElementAccess) { + const WideString abc(L"abc"); + EXPECT_EQ(L'a', abc[0]); + EXPECT_EQ(L'b', abc[1]); + EXPECT_EQ(L'c', abc[2]); +#ifndef NDEBUG + EXPECT_DEATH({ abc[4]; }, ".*"); +#endif + + WideString mutable_abc = abc; + EXPECT_EQ(abc.c_str(), mutable_abc.c_str()); + EXPECT_EQ(L'a', mutable_abc[0]); + EXPECT_EQ(L'b', mutable_abc[1]); + EXPECT_EQ(L'c', mutable_abc[2]); + EXPECT_EQ(abc.c_str(), mutable_abc.c_str()); + EXPECT_EQ(L"abc", abc); + + const wchar_t* c_str = abc.c_str(); + mutable_abc.SetAt(0, L'd'); + EXPECT_EQ(c_str, abc.c_str()); + EXPECT_NE(c_str, mutable_abc.c_str()); + EXPECT_EQ(L"abc", abc); + EXPECT_EQ(L"dbc", mutable_abc); + + mutable_abc.SetAt(1, L'e'); + EXPECT_EQ(L"abc", abc); + EXPECT_EQ(L"dec", mutable_abc); + + mutable_abc.SetAt(2, L'f'); + EXPECT_EQ(L"abc", abc); + EXPECT_EQ(L"def", mutable_abc); +#ifndef NDEBUG + EXPECT_DEATH({ mutable_abc.SetAt(3, L'g'); }, ".*"); + EXPECT_EQ(L"abc", abc); +#endif +} + +TEST(WideString, OperatorLT) { + WideString empty; + WideString a(L"a"); + WideString abc(L"\x0110qq"); // Comes before despite endianness. + WideString def(L"\x1001qq"); // Comes after despite endianness. + + EXPECT_FALSE(empty < empty); + EXPECT_FALSE(a < a); + EXPECT_FALSE(abc < abc); + EXPECT_FALSE(def < def); + + EXPECT_TRUE(empty < a); + EXPECT_FALSE(a < empty); + + EXPECT_TRUE(empty < abc); + EXPECT_FALSE(abc < empty); + + EXPECT_TRUE(empty < def); + EXPECT_FALSE(def < empty); + + EXPECT_TRUE(a < abc); + EXPECT_FALSE(abc < a); + + EXPECT_TRUE(a < def); + EXPECT_FALSE(def < a); + + EXPECT_TRUE(abc < def); + EXPECT_FALSE(def < abc); +} + +TEST(WideString, OperatorEQ) { + WideString null_string; + EXPECT_TRUE(null_string == null_string); + + WideString empty_string(L""); + EXPECT_TRUE(empty_string == empty_string); + EXPECT_TRUE(empty_string == null_string); + EXPECT_TRUE(null_string == empty_string); + + WideString deleted_string(L"hello"); + deleted_string.Delete(0, 5); + EXPECT_TRUE(deleted_string == deleted_string); + EXPECT_TRUE(deleted_string == null_string); + EXPECT_TRUE(deleted_string == empty_string); + EXPECT_TRUE(null_string == deleted_string); + EXPECT_TRUE(null_string == empty_string); + + WideString wide_string(L"hello"); + EXPECT_TRUE(wide_string == wide_string); + EXPECT_FALSE(wide_string == null_string); + EXPECT_FALSE(wide_string == empty_string); + EXPECT_FALSE(wide_string == deleted_string); + EXPECT_FALSE(null_string == wide_string); + EXPECT_FALSE(empty_string == wide_string); + EXPECT_FALSE(deleted_string == wide_string); + + WideString wide_string_same1(L"hello"); + EXPECT_TRUE(wide_string == wide_string_same1); + EXPECT_TRUE(wide_string_same1 == wide_string); + + WideString wide_string_same2(wide_string); + EXPECT_TRUE(wide_string == wide_string_same2); + EXPECT_TRUE(wide_string_same2 == wide_string); + + WideString wide_string1(L"he"); + WideString wide_string2(L"hellp"); + WideString wide_string3(L"hellod"); + EXPECT_FALSE(wide_string == wide_string1); + EXPECT_FALSE(wide_string == wide_string2); + EXPECT_FALSE(wide_string == wide_string3); + EXPECT_FALSE(wide_string1 == wide_string); + EXPECT_FALSE(wide_string2 == wide_string); + EXPECT_FALSE(wide_string3 == wide_string); + + WideStringView null_string_c; + WideStringView empty_string_c(L""); + EXPECT_TRUE(null_string == null_string_c); + EXPECT_TRUE(null_string == empty_string_c); + EXPECT_TRUE(empty_string == null_string_c); + EXPECT_TRUE(empty_string == empty_string_c); + EXPECT_TRUE(deleted_string == null_string_c); + EXPECT_TRUE(deleted_string == empty_string_c); + EXPECT_TRUE(null_string_c == null_string); + EXPECT_TRUE(empty_string_c == null_string); + EXPECT_TRUE(null_string_c == empty_string); + EXPECT_TRUE(empty_string_c == empty_string); + EXPECT_TRUE(null_string_c == deleted_string); + EXPECT_TRUE(empty_string_c == deleted_string); + + WideStringView wide_string_c_same1(L"hello"); + EXPECT_TRUE(wide_string == wide_string_c_same1); + EXPECT_TRUE(wide_string_c_same1 == wide_string); + + WideStringView wide_string_c1(L"he"); + WideStringView wide_string_c2(L"hellp"); + WideStringView wide_string_c3(L"hellod"); + EXPECT_FALSE(wide_string == wide_string_c1); + EXPECT_FALSE(wide_string == wide_string_c2); + EXPECT_FALSE(wide_string == wide_string_c3); + EXPECT_FALSE(wide_string_c1 == wide_string); + EXPECT_FALSE(wide_string_c2 == wide_string); + EXPECT_FALSE(wide_string_c3 == wide_string); + + const wchar_t* c_null_string = nullptr; + const wchar_t* c_empty_string = L""; + EXPECT_TRUE(null_string == c_null_string); + EXPECT_TRUE(null_string == c_empty_string); + EXPECT_TRUE(empty_string == c_null_string); + EXPECT_TRUE(empty_string == c_empty_string); + EXPECT_TRUE(deleted_string == c_null_string); + EXPECT_TRUE(deleted_string == c_empty_string); + EXPECT_TRUE(c_null_string == null_string); + EXPECT_TRUE(c_empty_string == null_string); + EXPECT_TRUE(c_null_string == empty_string); + EXPECT_TRUE(c_empty_string == empty_string); + EXPECT_TRUE(c_null_string == deleted_string); + EXPECT_TRUE(c_empty_string == deleted_string); + + const wchar_t* c_string_same1 = L"hello"; + EXPECT_TRUE(wide_string == c_string_same1); + EXPECT_TRUE(c_string_same1 == wide_string); + + const wchar_t* c_string1 = L"he"; + const wchar_t* c_string2 = L"hellp"; + const wchar_t* c_string3 = L"hellod"; + EXPECT_FALSE(wide_string == c_string1); + EXPECT_FALSE(wide_string == c_string2); + EXPECT_FALSE(wide_string == c_string3); + EXPECT_FALSE(c_string1 == wide_string); + EXPECT_FALSE(c_string2 == wide_string); + EXPECT_FALSE(c_string3 == wide_string); +} + +TEST(WideString, OperatorNE) { + WideString null_string; + EXPECT_FALSE(null_string != null_string); + + WideString empty_string(L""); + EXPECT_FALSE(empty_string != empty_string); + EXPECT_FALSE(empty_string != null_string); + EXPECT_FALSE(null_string != empty_string); + + WideString deleted_string(L"hello"); + deleted_string.Delete(0, 5); + EXPECT_FALSE(deleted_string != deleted_string); + EXPECT_FALSE(deleted_string != null_string); + EXPECT_FALSE(deleted_string != empty_string); + EXPECT_FALSE(null_string != deleted_string); + EXPECT_FALSE(null_string != empty_string); + + WideString wide_string(L"hello"); + EXPECT_FALSE(wide_string != wide_string); + EXPECT_TRUE(wide_string != null_string); + EXPECT_TRUE(wide_string != empty_string); + EXPECT_TRUE(wide_string != deleted_string); + EXPECT_TRUE(null_string != wide_string); + EXPECT_TRUE(empty_string != wide_string); + EXPECT_TRUE(deleted_string != wide_string); + + WideString wide_string_same1(L"hello"); + EXPECT_FALSE(wide_string != wide_string_same1); + EXPECT_FALSE(wide_string_same1 != wide_string); + + WideString wide_string_same2(wide_string); + EXPECT_FALSE(wide_string != wide_string_same2); + EXPECT_FALSE(wide_string_same2 != wide_string); + + WideString wide_string1(L"he"); + WideString wide_string2(L"hellp"); + WideString wide_string3(L"hellod"); + EXPECT_TRUE(wide_string != wide_string1); + EXPECT_TRUE(wide_string != wide_string2); + EXPECT_TRUE(wide_string != wide_string3); + EXPECT_TRUE(wide_string1 != wide_string); + EXPECT_TRUE(wide_string2 != wide_string); + EXPECT_TRUE(wide_string3 != wide_string); + + WideStringView null_string_c; + WideStringView empty_string_c(L""); + EXPECT_FALSE(null_string != null_string_c); + EXPECT_FALSE(null_string != empty_string_c); + EXPECT_FALSE(empty_string != null_string_c); + EXPECT_FALSE(empty_string != empty_string_c); + EXPECT_FALSE(deleted_string != null_string_c); + EXPECT_FALSE(deleted_string != empty_string_c); + EXPECT_FALSE(null_string_c != null_string); + EXPECT_FALSE(empty_string_c != null_string); + EXPECT_FALSE(null_string_c != empty_string); + EXPECT_FALSE(empty_string_c != empty_string); + + WideStringView wide_string_c_same1(L"hello"); + EXPECT_FALSE(wide_string != wide_string_c_same1); + EXPECT_FALSE(wide_string_c_same1 != wide_string); + + WideStringView wide_string_c1(L"he"); + WideStringView wide_string_c2(L"hellp"); + WideStringView wide_string_c3(L"hellod"); + EXPECT_TRUE(wide_string != wide_string_c1); + EXPECT_TRUE(wide_string != wide_string_c2); + EXPECT_TRUE(wide_string != wide_string_c3); + EXPECT_TRUE(wide_string_c1 != wide_string); + EXPECT_TRUE(wide_string_c2 != wide_string); + EXPECT_TRUE(wide_string_c3 != wide_string); + + const wchar_t* c_null_string = nullptr; + const wchar_t* c_empty_string = L""; + EXPECT_FALSE(null_string != c_null_string); + EXPECT_FALSE(null_string != c_empty_string); + EXPECT_FALSE(empty_string != c_null_string); + EXPECT_FALSE(empty_string != c_empty_string); + EXPECT_FALSE(deleted_string != c_null_string); + EXPECT_FALSE(deleted_string != c_empty_string); + EXPECT_FALSE(c_null_string != null_string); + EXPECT_FALSE(c_empty_string != null_string); + EXPECT_FALSE(c_null_string != empty_string); + EXPECT_FALSE(c_empty_string != empty_string); + EXPECT_FALSE(c_null_string != deleted_string); + EXPECT_FALSE(c_empty_string != deleted_string); + + const wchar_t* c_string_same1 = L"hello"; + EXPECT_FALSE(wide_string != c_string_same1); + EXPECT_FALSE(c_string_same1 != wide_string); + + const wchar_t* c_string1 = L"he"; + const wchar_t* c_string2 = L"hellp"; + const wchar_t* c_string3 = L"hellod"; + EXPECT_TRUE(wide_string != c_string1); + EXPECT_TRUE(wide_string != c_string2); + EXPECT_TRUE(wide_string != c_string3); + EXPECT_TRUE(c_string1 != wide_string); + EXPECT_TRUE(c_string2 != wide_string); + EXPECT_TRUE(c_string3 != wide_string); +} + +TEST(WideString, ConcatInPlace) { + WideString fred; + fred.Concat(L"FRED", 4); + EXPECT_EQ(L"FRED", fred); + + fred.Concat(L"DY", 2); + EXPECT_EQ(L"FREDDY", fred); + + fred.Delete(3, 3); + EXPECT_EQ(L"FRE", fred); + + fred.Concat(L"D", 1); + EXPECT_EQ(L"FRED", fred); + + WideString copy = fred; + fred.Concat(L"DY", 2); + EXPECT_EQ(L"FREDDY", fred); + EXPECT_EQ(L"FRED", copy); +} + +TEST(WideString, Remove) { + WideString freed(L"FREED"); + freed.Remove(L'E'); + EXPECT_EQ(L"FRD", freed); + freed.Remove(L'F'); + EXPECT_EQ(L"RD", freed); + freed.Remove(L'D'); + EXPECT_EQ(L"R", freed); + freed.Remove(L'X'); + EXPECT_EQ(L"R", freed); + freed.Remove(L'R'); + EXPECT_EQ(L"", freed); + + WideString empty; + empty.Remove(L'X'); + EXPECT_EQ(L"", empty); +} + +TEST(WideString, RemoveCopies) { + WideString freed(L"FREED"); + const wchar_t* old_buffer = freed.c_str(); + + // No change with single reference - no copy. + freed.Remove(L'Q'); + EXPECT_EQ(L"FREED", freed); + EXPECT_EQ(old_buffer, freed.c_str()); + + // Change with single reference - no copy. + freed.Remove(L'E'); + EXPECT_EQ(L"FRD", freed); + EXPECT_EQ(old_buffer, freed.c_str()); + + // No change with multiple references - no copy. + WideString shared(freed); + freed.Remove(L'Q'); + EXPECT_EQ(L"FRD", freed); + EXPECT_EQ(old_buffer, freed.c_str()); + EXPECT_EQ(old_buffer, shared.c_str()); + + // Change with multiple references -- must copy. + freed.Remove(L'D'); + EXPECT_EQ(L"FR", freed); + EXPECT_NE(old_buffer, freed.c_str()); + EXPECT_EQ(L"FRD", shared); + EXPECT_EQ(old_buffer, shared.c_str()); +} + +TEST(WideString, Replace) { + WideString fred(L"FRED"); + fred.Replace(L"FR", L"BL"); + EXPECT_EQ(L"BLED", fred); + fred.Replace(L"D", L"DDY"); + EXPECT_EQ(L"BLEDDY", fred); + fred.Replace(L"LEDD", L""); + EXPECT_EQ(L"BY", fred); + fred.Replace(L"X", L"CLAMS"); + EXPECT_EQ(L"BY", fred); + fred.Replace(L"BY", L"HI"); + EXPECT_EQ(L"HI", fred); + fred.Replace(L"", L"CLAMS"); + EXPECT_EQ(L"HI", fred); + fred.Replace(L"HI", L""); + EXPECT_EQ(L"", fred); +} + +TEST(WideString, Insert) { + WideString fred(L"FRED"); + EXPECT_EQ(5u, fred.Insert(0, 'S')); + EXPECT_EQ(L"SFRED", fred); + EXPECT_EQ(6u, fred.Insert(1, 'T')); + EXPECT_EQ(L"STFRED", fred); + EXPECT_EQ(7u, fred.Insert(4, 'U')); + EXPECT_EQ(L"STFRUED", fred); + EXPECT_EQ(8u, fred.Insert(7, 'V')); + EXPECT_EQ(L"STFRUEDV", fred); + EXPECT_EQ(8u, fred.Insert(12, 'P')); + EXPECT_EQ(L"STFRUEDV", fred); + { + WideString empty; + EXPECT_EQ(1u, empty.Insert(0, 'X')); + EXPECT_EQ(L"X", empty); + } + { + WideString empty; + EXPECT_EQ(0u, empty.Insert(5, 'X')); + EXPECT_NE(L"X", empty); + } +} + +TEST(WideString, InsertAtFrontAndInsertAtBack) { + { + WideString empty; + EXPECT_EQ(1u, empty.InsertAtFront('D')); + EXPECT_EQ(L"D", empty); + EXPECT_EQ(2u, empty.InsertAtFront('E')); + EXPECT_EQ(L"ED", empty); + EXPECT_EQ(3u, empty.InsertAtFront('R')); + EXPECT_EQ(L"RED", empty); + EXPECT_EQ(4u, empty.InsertAtFront('F')); + EXPECT_EQ(L"FRED", empty); + } + { + WideString empty; + EXPECT_EQ(1u, empty.InsertAtBack('F')); + EXPECT_EQ(L"F", empty); + EXPECT_EQ(2u, empty.InsertAtBack('R')); + EXPECT_EQ(L"FR", empty); + EXPECT_EQ(3u, empty.InsertAtBack('E')); + EXPECT_EQ(L"FRE", empty); + EXPECT_EQ(4u, empty.InsertAtBack('D')); + EXPECT_EQ(L"FRED", empty); + } + { + WideString empty; + EXPECT_EQ(1u, empty.InsertAtBack('E')); + EXPECT_EQ(L"E", empty); + EXPECT_EQ(2u, empty.InsertAtFront('R')); + EXPECT_EQ(L"RE", empty); + EXPECT_EQ(3u, empty.InsertAtBack('D')); + EXPECT_EQ(L"RED", empty); + EXPECT_EQ(4u, empty.InsertAtFront('F')); + EXPECT_EQ(L"FRED", empty); + } +} + +TEST(WideString, Delete) { + WideString fred(L"FRED"); + EXPECT_EQ(4u, fred.Delete(0, 0)); + EXPECT_EQ(L"FRED", fred); + EXPECT_EQ(2u, fred.Delete(0, 2)); + EXPECT_EQ(L"ED", fred); + EXPECT_EQ(1u, fred.Delete(1)); + EXPECT_EQ(L"E", fred); + EXPECT_EQ(0u, fred.Delete(0)); + EXPECT_EQ(L"", fred); + EXPECT_EQ(0u, fred.Delete(0)); + EXPECT_EQ(L"", fred); + + WideString empty; + EXPECT_EQ(0u, empty.Delete(0)); + EXPECT_EQ(L"", empty); + EXPECT_EQ(0u, empty.Delete(1)); + EXPECT_EQ(L"", empty); +} + +TEST(WideString, Mid) { + WideString fred(L"FRED"); + EXPECT_EQ(L"", fred.Mid(0, 0)); + EXPECT_EQ(L"", fred.Mid(3, 0)); + EXPECT_EQ(L"FRED", fred.Mid(0, 4)); + EXPECT_EQ(L"RED", fred.Mid(1, 3)); + EXPECT_EQ(L"ED", fred.Mid(2, 2)); + EXPECT_EQ(L"D", fred.Mid(3, 1)); + EXPECT_EQ(L"F", fred.Mid(0, 1)); + EXPECT_EQ(L"R", fred.Mid(1, 1)); + EXPECT_EQ(L"E", fred.Mid(2, 1)); + EXPECT_EQ(L"D", fred.Mid(3, 1)); + EXPECT_EQ(L"FR", fred.Mid(0, 2)); + EXPECT_EQ(L"FRED", fred.Mid(0, 4)); + EXPECT_EQ(L"", fred.Mid(0, 10)); + + EXPECT_EQ(L"", fred.Mid(1, 4)); + EXPECT_EQ(L"", fred.Mid(4, 1)); + + WideString empty; + EXPECT_EQ(L"", empty.Mid(0, 0)); +} + +TEST(WideString, Left) { + WideString fred(L"FRED"); + EXPECT_EQ(L"", fred.Left(0)); + EXPECT_EQ(L"F", fred.Left(1)); + EXPECT_EQ(L"FR", fred.Left(2)); + EXPECT_EQ(L"FRE", fred.Left(3)); + EXPECT_EQ(L"FRED", fred.Left(4)); + + EXPECT_EQ(L"", fred.Left(5)); + + WideString empty; + EXPECT_EQ(L"", empty.Left(0)); + EXPECT_EQ(L"", empty.Left(1)); +} + +TEST(WideString, Right) { + WideString fred(L"FRED"); + EXPECT_EQ(L"", fred.Right(0)); + EXPECT_EQ(L"D", fred.Right(1)); + EXPECT_EQ(L"ED", fred.Right(2)); + EXPECT_EQ(L"RED", fred.Right(3)); + EXPECT_EQ(L"FRED", fred.Right(4)); + + EXPECT_EQ(L"", fred.Right(5)); + + WideString empty; + EXPECT_EQ(L"", empty.Right(0)); + EXPECT_EQ(L"", empty.Right(1)); +} + +TEST(WideString, Find) { + WideString null_string; + EXPECT_FALSE(null_string.Find(L'a').has_value()); + EXPECT_FALSE(null_string.Find(L'\0').has_value()); + + WideString empty_string(L""); + EXPECT_FALSE(empty_string.Find(L'a').has_value()); + EXPECT_FALSE(empty_string.Find(L'\0').has_value()); + + pdfium::Optional result; + WideString single_string(L"a"); + result = single_string.Find(L'a'); + ASSERT_TRUE(result.has_value()); + EXPECT_EQ(0u, result.value()); + EXPECT_FALSE(single_string.Find(L'b').has_value()); + EXPECT_FALSE(single_string.Find(L'\0').has_value()); + + WideString longer_string(L"abccc"); + result = longer_string.Find(L'a'); + ASSERT_TRUE(result.has_value()); + EXPECT_EQ(0u, result.value()); + result = longer_string.Find(L'c'); + ASSERT_TRUE(result.has_value()); + EXPECT_EQ(2u, result.value()); + result = longer_string.Find(L'c', 3); + ASSERT_TRUE(result.has_value()); + EXPECT_EQ(3u, result.value()); + EXPECT_FALSE(longer_string.Find(L'\0').has_value()); + + result = longer_string.Find(L"ab"); + ASSERT_TRUE(result.has_value()); + EXPECT_EQ(0u, result.value()); + result = longer_string.Find(L"ccc"); + ASSERT_TRUE(result.has_value()); + EXPECT_EQ(2u, result.value()); + result = longer_string.Find(L"cc", 3); + ASSERT_TRUE(result.has_value()); + EXPECT_EQ(3u, result.value()); + EXPECT_FALSE(longer_string.Find(L"d").has_value()); + + WideString hibyte_string( + L"ab\xff8c" + L"def"); + result = hibyte_string.Find(L'\xff8c'); + ASSERT_TRUE(result.has_value()); + EXPECT_EQ(2u, result.value()); +} + +TEST(WideString, UpperLower) { + WideString fred(L"F-Re.42D"); + fred.MakeLower(); + EXPECT_EQ(L"f-re.42d", fred); + fred.MakeUpper(); + EXPECT_EQ(L"F-RE.42D", fred); + + WideString empty; + empty.MakeLower(); + EXPECT_EQ(L"", empty); + empty.MakeUpper(); + EXPECT_EQ(L"", empty); +} + +TEST(WideString, TrimRight) { + WideString fred(L" FRED "); + fred.TrimRight(); + EXPECT_EQ(L" FRED", fred); + fred.TrimRight(L'E'); + EXPECT_EQ(L" FRED", fred); + fred.TrimRight(L'D'); + EXPECT_EQ(L" FRE", fred); + fred.TrimRight(L"ERP"); + EXPECT_EQ(L" F", fred); + + WideString blank(L" "); + blank.TrimRight(L"ERP"); + EXPECT_EQ(L" ", blank); + blank.TrimRight(L'E'); + EXPECT_EQ(L" ", blank); + blank.TrimRight(); + EXPECT_EQ(L"", blank); + + WideString empty; + empty.TrimRight(L"ERP"); + EXPECT_EQ(L"", empty); + empty.TrimRight(L'E'); + EXPECT_EQ(L"", empty); + empty.TrimRight(); + EXPECT_EQ(L"", empty); +} + +TEST(WideString, TrimRightCopies) { + { + // With a single reference, no copy takes place. + WideString fred(L" FRED "); + const wchar_t* old_buffer = fred.c_str(); + fred.TrimRight(); + EXPECT_EQ(L" FRED", fred); + EXPECT_EQ(old_buffer, fred.c_str()); + } + { + // With multiple references, we must copy. + WideString fred(L" FRED "); + WideString other_fred = fred; + const wchar_t* old_buffer = fred.c_str(); + fred.TrimRight(); + EXPECT_EQ(L" FRED", fred); + EXPECT_EQ(L" FRED ", other_fred); + EXPECT_NE(old_buffer, fred.c_str()); + } + { + // With multiple references, but no modifications, no copy. + WideString fred(L"FRED"); + WideString other_fred = fred; + const wchar_t* old_buffer = fred.c_str(); + fred.TrimRight(); + EXPECT_EQ(L"FRED", fred); + EXPECT_EQ(L"FRED", other_fred); + EXPECT_EQ(old_buffer, fred.c_str()); + } +} + +TEST(WideString, TrimLeft) { + WideString fred(L" FRED "); + fred.TrimLeft(); + EXPECT_EQ(L"FRED ", fred); + fred.TrimLeft(L'E'); + EXPECT_EQ(L"FRED ", fred); + fred.TrimLeft(L'F'); + EXPECT_EQ(L"RED ", fred); + fred.TrimLeft(L"ERP"); + EXPECT_EQ(L"D ", fred); + + WideString blank(L" "); + blank.TrimLeft(L"ERP"); + EXPECT_EQ(L" ", blank); + blank.TrimLeft(L'E'); + EXPECT_EQ(L" ", blank); + blank.TrimLeft(); + EXPECT_EQ(L"", blank); + + WideString empty; + empty.TrimLeft(L"ERP"); + EXPECT_EQ(L"", empty); + empty.TrimLeft(L'E'); + EXPECT_EQ(L"", empty); + empty.TrimLeft(); + EXPECT_EQ(L"", empty); +} + +TEST(WideString, TrimLeftCopies) { + { + // With a single reference, no copy takes place. + WideString fred(L" FRED "); + const wchar_t* old_buffer = fred.c_str(); + fred.TrimLeft(); + EXPECT_EQ(L"FRED ", fred); + EXPECT_EQ(old_buffer, fred.c_str()); + } + { + // With multiple references, we must copy. + WideString fred(L" FRED "); + WideString other_fred = fred; + const wchar_t* old_buffer = fred.c_str(); + fred.TrimLeft(); + EXPECT_EQ(L"FRED ", fred); + EXPECT_EQ(L" FRED ", other_fred); + EXPECT_NE(old_buffer, fred.c_str()); + } + { + // With multiple references, but no modifications, no copy. + WideString fred(L"FRED"); + WideString other_fred = fred; + const wchar_t* old_buffer = fred.c_str(); + fred.TrimLeft(); + EXPECT_EQ(L"FRED", fred); + EXPECT_EQ(L"FRED", other_fred); + EXPECT_EQ(old_buffer, fred.c_str()); + } +} + +TEST(WideString, Reserve) { + { + WideString str; + str.Reserve(6); + const wchar_t* old_buffer = str.c_str(); + str += L"ABCDEF"; + EXPECT_EQ(old_buffer, str.c_str()); + str += L"Blah Blah Blah Blah Blah Blah"; + EXPECT_NE(old_buffer, str.c_str()); + } + { + WideString str(L"A"); + str.Reserve(6); + const wchar_t* old_buffer = str.c_str(); + str += L"BCDEF"; + EXPECT_EQ(old_buffer, str.c_str()); + str += L"Blah Blah Blah Blah Blah Blah"; + EXPECT_NE(old_buffer, str.c_str()); + } +} + +TEST(WideString, GetBuffer) { + { + WideString str; + wchar_t* buffer = str.GetBuffer(12); + wcscpy(buffer, L"clams"); + str.ReleaseBuffer(str.GetStringLength()); + EXPECT_EQ(L"clams", str); + } + { + WideString str(L"cl"); + wchar_t* buffer = str.GetBuffer(12); + wcscpy(buffer + 2, L"ams"); + str.ReleaseBuffer(str.GetStringLength()); + EXPECT_EQ(L"clams", str); + } +} + +TEST(WideString, ReleaseBuffer) { + { + WideString str; + str.Reserve(12); + str += L"clams"; + const wchar_t* old_buffer = str.c_str(); + str.ReleaseBuffer(4); + EXPECT_EQ(old_buffer, str.c_str()); + EXPECT_EQ(L"clam", str); + } + { + WideString str(L"c"); + str.Reserve(12); + str += L"lams"; + const wchar_t* old_buffer = str.c_str(); + str.ReleaseBuffer(4); + EXPECT_EQ(old_buffer, str.c_str()); + EXPECT_EQ(L"clam", str); + } + { + WideString str; + str.Reserve(200); + str += L"clams"; + const wchar_t* old_buffer = str.c_str(); + str.ReleaseBuffer(4); + EXPECT_NE(old_buffer, str.c_str()); + EXPECT_EQ(L"clam", str); + } + { + WideString str(L"c"); + str.Reserve(200); + str += L"lams"; + const wchar_t* old_buffer = str.c_str(); + str.ReleaseBuffer(4); + EXPECT_NE(old_buffer, str.c_str()); + EXPECT_EQ(L"clam", str); + } +} + +TEST(WideString, EmptyReverseIterator) { + WideString empty; + auto iter = empty.rbegin(); + EXPECT_TRUE(iter == empty.rend()); + EXPECT_FALSE(iter != empty.rend()); + EXPECT_FALSE(iter < empty.rend()); +} + +TEST(WideString, OneCharReverseIterator) { + WideString one_str(L"a"); + auto iter = one_str.rbegin(); + EXPECT_FALSE(iter == one_str.rend()); + EXPECT_TRUE(iter != one_str.rend()); + EXPECT_TRUE(iter < one_str.rend()); + + char ch = *iter++; + EXPECT_EQ('a', ch); + EXPECT_TRUE(iter == one_str.rend()); + EXPECT_FALSE(iter != one_str.rend()); + EXPECT_FALSE(iter < one_str.rend()); +} + +TEST(WideString, MultiCharReverseIterator) { + WideString multi_str(L"abcd"); + auto iter = multi_str.rbegin(); + EXPECT_FALSE(iter == multi_str.rend()); + + char ch = *iter++; + EXPECT_EQ('d', ch); + EXPECT_EQ('c', *iter); + EXPECT_FALSE(iter == multi_str.rend()); + + ch = *(++iter); + EXPECT_EQ('b', ch); + EXPECT_EQ('b', *iter); + EXPECT_FALSE(iter == multi_str.rend()); + + ch = *iter++; + EXPECT_EQ('b', ch); + EXPECT_EQ('a', *iter); + EXPECT_FALSE(iter == multi_str.rend()); + + ch = *iter++; + EXPECT_EQ('a', ch); + EXPECT_TRUE(iter == multi_str.rend()); + + ch = *(--iter); + EXPECT_EQ('a', ch); + EXPECT_EQ('a', *iter); + EXPECT_FALSE(iter == multi_str.rend()); + + ch = *iter--; + EXPECT_EQ('a', ch); + EXPECT_EQ('b', *iter); + EXPECT_FALSE(iter == multi_str.rend()); + + ch = *iter--; + EXPECT_EQ('b', ch); + EXPECT_EQ('c', *iter); + EXPECT_FALSE(iter == multi_str.rend()); + + ch = *(--iter); + EXPECT_EQ('d', ch); + EXPECT_EQ('d', *iter); + EXPECT_TRUE(iter == multi_str.rbegin()); +} + +TEST(WideString, UTF16LE_Encode) { + struct UTF16LEEncodeCase { + WideString ws; + ByteString bs; + } utf16le_encode_cases[] = { + {L"", ByteString("\0\0", 2)}, + {L"abc", ByteString("a\0b\0c\0\0\0", 8)}, + {L"abcdef", ByteString("a\0b\0c\0d\0e\0f\0\0\0", 14)}, + {L"abc\0def", ByteString("a\0b\0c\0\0\0", 8)}, + {L"\xaabb\xccdd", ByteString("\xbb\xaa\xdd\xcc\0\0", 6)}, + {L"\x3132\x6162", ByteString("\x32\x31\x62\x61\0\0", 6)}, + }; + + for (size_t i = 0; i < FX_ArraySize(utf16le_encode_cases); ++i) { + EXPECT_EQ(utf16le_encode_cases[i].bs, + utf16le_encode_cases[i].ws.UTF16LE_Encode()) + << " for case number " << i; + } +} + +TEST(WideStringView, FromVector) { + std::vector null_vec; + WideStringView null_string(null_vec); + EXPECT_EQ(0u, null_string.GetLength()); + + std::vector lower_a_vec( + 10, static_cast(L'a')); + WideStringView lower_a_string(lower_a_vec); + EXPECT_EQ(10u, lower_a_string.GetLength()); + EXPECT_EQ(L"aaaaaaaaaa", lower_a_string); + + std::vector cleared_vec; + cleared_vec.push_back(42); + cleared_vec.pop_back(); + WideStringView cleared_string(cleared_vec); + EXPECT_EQ(0u, cleared_string.GetLength()); + EXPECT_EQ(nullptr, cleared_string.raw_str()); +} + +TEST(WideStringView, ElementAccess) { + WideStringView abc(L"abc"); + EXPECT_EQ(L'a', static_cast(abc[0])); + EXPECT_EQ(L'b', static_cast(abc[1])); + EXPECT_EQ(L'c', static_cast(abc[2])); +#ifndef NDEBUG + EXPECT_DEATH({ abc[4]; }, ".*"); +#endif +} + +TEST(WideStringView, OperatorLT) { + WideStringView empty; + WideStringView a(L"a"); + WideStringView abc(L"\x0110qq"); // Comes InsertAtFront despite endianness. + WideStringView def(L"\x1001qq"); // Comes InsertAtBack despite endianness. + + EXPECT_FALSE(empty < empty); + EXPECT_FALSE(a < a); + EXPECT_FALSE(abc < abc); + EXPECT_FALSE(def < def); + + EXPECT_TRUE(empty < a); + EXPECT_FALSE(a < empty); + + EXPECT_TRUE(empty < abc); + EXPECT_FALSE(abc < empty); + + EXPECT_TRUE(empty < def); + EXPECT_FALSE(def < empty); + + EXPECT_TRUE(a < abc); + EXPECT_FALSE(abc < a); + + EXPECT_TRUE(a < def); + EXPECT_FALSE(def < a); + + EXPECT_TRUE(abc < def); + EXPECT_FALSE(def < abc); +} + +TEST(WideStringView, OperatorEQ) { + WideStringView wide_string_c(L"hello"); + EXPECT_TRUE(wide_string_c == wide_string_c); + + WideStringView wide_string_c_same1(L"hello"); + EXPECT_TRUE(wide_string_c == wide_string_c_same1); + EXPECT_TRUE(wide_string_c_same1 == wide_string_c); + + WideStringView wide_string_c_same2(wide_string_c); + EXPECT_TRUE(wide_string_c == wide_string_c_same2); + EXPECT_TRUE(wide_string_c_same2 == wide_string_c); + + WideStringView wide_string_c1(L"he"); + WideStringView wide_string_c2(L"hellp"); + WideStringView wide_string_c3(L"hellod"); + EXPECT_FALSE(wide_string_c == wide_string_c1); + EXPECT_FALSE(wide_string_c == wide_string_c2); + EXPECT_FALSE(wide_string_c == wide_string_c3); + EXPECT_FALSE(wide_string_c1 == wide_string_c); + EXPECT_FALSE(wide_string_c2 == wide_string_c); + EXPECT_FALSE(wide_string_c3 == wide_string_c); + + WideString wide_string_same1(L"hello"); + EXPECT_TRUE(wide_string_c == wide_string_same1); + EXPECT_TRUE(wide_string_same1 == wide_string_c); + + WideString wide_string1(L"he"); + WideString wide_string2(L"hellp"); + WideString wide_string3(L"hellod"); + EXPECT_FALSE(wide_string_c == wide_string1); + EXPECT_FALSE(wide_string_c == wide_string2); + EXPECT_FALSE(wide_string_c == wide_string3); + EXPECT_FALSE(wide_string1 == wide_string_c); + EXPECT_FALSE(wide_string2 == wide_string_c); + EXPECT_FALSE(wide_string3 == wide_string_c); + + const wchar_t* c_string_same1 = L"hello"; + EXPECT_TRUE(wide_string_c == c_string_same1); + EXPECT_TRUE(c_string_same1 == wide_string_c); + + const wchar_t* c_string1 = L"he"; + const wchar_t* c_string2 = L"hellp"; + const wchar_t* c_string3 = L"hellod"; + EXPECT_FALSE(wide_string_c == c_string1); + EXPECT_FALSE(wide_string_c == c_string2); + EXPECT_FALSE(wide_string_c == c_string3); + + EXPECT_FALSE(c_string1 == wide_string_c); + EXPECT_FALSE(c_string2 == wide_string_c); + EXPECT_FALSE(c_string3 == wide_string_c); +} + +TEST(WideStringView, OperatorNE) { + WideStringView wide_string_c(L"hello"); + EXPECT_FALSE(wide_string_c != wide_string_c); + + WideStringView wide_string_c_same1(L"hello"); + EXPECT_FALSE(wide_string_c != wide_string_c_same1); + EXPECT_FALSE(wide_string_c_same1 != wide_string_c); + + WideStringView wide_string_c_same2(wide_string_c); + EXPECT_FALSE(wide_string_c != wide_string_c_same2); + EXPECT_FALSE(wide_string_c_same2 != wide_string_c); + + WideStringView wide_string_c1(L"he"); + WideStringView wide_string_c2(L"hellp"); + WideStringView wide_string_c3(L"hellod"); + EXPECT_TRUE(wide_string_c != wide_string_c1); + EXPECT_TRUE(wide_string_c != wide_string_c2); + EXPECT_TRUE(wide_string_c != wide_string_c3); + EXPECT_TRUE(wide_string_c1 != wide_string_c); + EXPECT_TRUE(wide_string_c2 != wide_string_c); + EXPECT_TRUE(wide_string_c3 != wide_string_c); + + WideString wide_string_same1(L"hello"); + EXPECT_FALSE(wide_string_c != wide_string_same1); + EXPECT_FALSE(wide_string_same1 != wide_string_c); + + WideString wide_string1(L"he"); + WideString wide_string2(L"hellp"); + WideString wide_string3(L"hellod"); + EXPECT_TRUE(wide_string_c != wide_string1); + EXPECT_TRUE(wide_string_c != wide_string2); + EXPECT_TRUE(wide_string_c != wide_string3); + EXPECT_TRUE(wide_string1 != wide_string_c); + EXPECT_TRUE(wide_string2 != wide_string_c); + EXPECT_TRUE(wide_string3 != wide_string_c); + + const wchar_t* c_string_same1 = L"hello"; + EXPECT_FALSE(wide_string_c != c_string_same1); + EXPECT_FALSE(c_string_same1 != wide_string_c); + + const wchar_t* c_string1 = L"he"; + const wchar_t* c_string2 = L"hellp"; + const wchar_t* c_string3 = L"hellod"; + EXPECT_TRUE(wide_string_c != c_string1); + EXPECT_TRUE(wide_string_c != c_string2); + EXPECT_TRUE(wide_string_c != c_string3); + + EXPECT_TRUE(c_string1 != wide_string_c); + EXPECT_TRUE(c_string2 != wide_string_c); + EXPECT_TRUE(c_string3 != wide_string_c); +} + +TEST(WideStringView, Find) { + WideStringView null_string; + EXPECT_FALSE(null_string.Find(L'a').has_value()); + EXPECT_FALSE(null_string.Find(L'\0').has_value()); + + WideStringView empty_string(L""); + EXPECT_FALSE(empty_string.Find(L'a').has_value()); + EXPECT_FALSE(empty_string.Find(L'\0').has_value()); + + pdfium::Optional result; + WideStringView single_string(L"a"); + result = single_string.Find(L'a'); + ASSERT_TRUE(result.has_value()); + EXPECT_EQ(0u, result.value()); + EXPECT_FALSE(single_string.Find(L'b').has_value()); + EXPECT_FALSE(single_string.Find(L'\0').has_value()); + + WideStringView longer_string(L"abccc"); + result = longer_string.Find(L'a'); + ASSERT_TRUE(result.has_value()); + EXPECT_EQ(0u, result.value()); + result = longer_string.Find(L'c'); + ASSERT_TRUE(result.has_value()); + EXPECT_EQ(2u, result.value()); + EXPECT_FALSE(longer_string.Find(L'd').has_value()); + EXPECT_FALSE(longer_string.Find(L'\0').has_value()); + + WideStringView hibyte_string( + L"ab\xFF8c" + L"def"); + result = hibyte_string.Find(L'\xFF8c'); + ASSERT_TRUE(result.has_value()); + EXPECT_EQ(2u, result.value()); +} + +TEST(WideStringView, NullIterator) { + WideStringView null_str; + int32_t sum = 0; + bool any_present = false; + for (const auto& c : null_str) { + sum += c; // Avoid unused arg warnings. + any_present = true; + } + EXPECT_FALSE(any_present); + EXPECT_EQ(0, sum); +} + +TEST(WideStringView, EmptyIterator) { + WideStringView empty_str(L""); + int32_t sum = 0; + bool any_present = false; + for (const auto& c : empty_str) { + any_present = true; + sum += c; // Avoid unused arg warnings. + } + EXPECT_FALSE(any_present); + EXPECT_EQ(0, sum); +} + +TEST(WideStringView, OneCharIterator) { + WideStringView one_str(L"a"); + int32_t sum = 0; + bool any_present = false; + for (const auto& c : one_str) { + any_present = true; + sum += c; // Avoid unused arg warnings. + } + EXPECT_TRUE(any_present); + EXPECT_EQ(static_cast(L'a'), sum); +} + +TEST(WideStringView, MultiCharIterator) { + WideStringView one_str(L"abc"); + int32_t sum = 0; + bool any_present = false; + for (const auto& c : one_str) { + any_present = true; + sum += c; // Avoid unused arg warnings. + } + EXPECT_TRUE(any_present); + EXPECT_EQ(static_cast(L'a' + L'b' + L'c'), sum); +} + +TEST(WideStringView, EmptyReverseIterator) { + WideStringView empty; + auto iter = empty.rbegin(); + EXPECT_TRUE(iter == empty.rend()); + EXPECT_FALSE(iter != empty.rend()); + EXPECT_FALSE(iter < empty.rend()); +} + +TEST(WideStringView, OneCharReverseIterator) { + WideStringView one_str(L"a"); + auto iter = one_str.rbegin(); + EXPECT_FALSE(iter == one_str.rend()); + EXPECT_TRUE(iter != one_str.rend()); + EXPECT_TRUE(iter < one_str.rend()); + + char ch = *iter++; + EXPECT_EQ('a', ch); + EXPECT_TRUE(iter == one_str.rend()); + EXPECT_FALSE(iter != one_str.rend()); + EXPECT_FALSE(iter < one_str.rend()); +} + +TEST(WideStringView, MultiCharReverseIterator) { + WideStringView multi_str(L"abcd"); + auto iter = multi_str.rbegin(); + EXPECT_FALSE(iter == multi_str.rend()); + + char ch = *iter++; + EXPECT_EQ('d', ch); + EXPECT_EQ('c', *iter); + EXPECT_FALSE(iter == multi_str.rend()); + + ch = *(++iter); + EXPECT_EQ('b', ch); + EXPECT_EQ('b', *iter); + EXPECT_FALSE(iter == multi_str.rend()); + + ch = *iter++; + EXPECT_EQ('b', ch); + EXPECT_EQ('a', *iter); + EXPECT_FALSE(iter == multi_str.rend()); + + ch = *iter++; + EXPECT_EQ('a', ch); + EXPECT_TRUE(iter == multi_str.rend()); + + ch = *(--iter); + EXPECT_EQ('a', ch); + EXPECT_EQ('a', *iter); + EXPECT_FALSE(iter == multi_str.rend()); + + ch = *iter--; + EXPECT_EQ('a', ch); + EXPECT_EQ('b', *iter); + EXPECT_FALSE(iter == multi_str.rend()); + + ch = *iter--; + EXPECT_EQ('b', ch); + EXPECT_EQ('c', *iter); + EXPECT_FALSE(iter == multi_str.rend()); + + ch = *(--iter); + EXPECT_EQ('d', ch); + EXPECT_EQ('d', *iter); + EXPECT_TRUE(iter == multi_str.rbegin()); +} + +TEST(WideStringView, AnyAllNoneOf) { + WideStringView str(L"aaaaaaaaaaaaaaaaab"); + EXPECT_FALSE(std::all_of(str.begin(), str.end(), + [](const wchar_t& c) { return c == L'a'; })); + + EXPECT_FALSE(std::none_of(str.begin(), str.end(), + [](const wchar_t& c) { return c == L'a'; })); + + EXPECT_TRUE(std::any_of(str.begin(), str.end(), + [](const wchar_t& c) { return c == L'a'; })); + + EXPECT_TRUE(pdfium::ContainsValue(str, L'a')); + EXPECT_TRUE(pdfium::ContainsValue(str, L'b')); + EXPECT_FALSE(pdfium::ContainsValue(str, L'z')); +} + +TEST(WideStringView, TrimmedRight) { + WideStringView fred(L"FRED"); + EXPECT_EQ(L"FRED", fred.TrimmedRight(L'E')); + EXPECT_EQ(L"FRE", fred.TrimmedRight(L'D')); + WideStringView fredd(L"FREDD"); + EXPECT_EQ(L"FRE", fred.TrimmedRight(L'D')); +} + +TEST(WideString, FormatWidth) { + { + WideString str; + str.Format(L"%5d", 1); + EXPECT_EQ(L" 1", str); + } + + { + WideString str; + str.Format(L"%d", 1); + EXPECT_EQ(L"1", str); + } + + { + WideString str; + str.Format(L"%*d", 5, 1); + EXPECT_EQ(L" 1", str); + } + + { + WideString str; + str.Format(L"%-1d", 1); + EXPECT_EQ(L"1", str); + } + + { + WideString str; + str.Format(L"%0d", 1); + EXPECT_EQ(L"1", str); + } + + { + WideString str; + str.Format(L"%1048576d", 1); + EXPECT_EQ(L"", str); + } +} + +TEST(WideString, FormatPrecision) { + { + WideString str; + str.Format(L"%.2f", 1.12345); + EXPECT_EQ(L"1.12", str); + } + + { + WideString str; + str.Format(L"%.*f", 3, 1.12345); + EXPECT_EQ(L"1.123", str); + } + + { + WideString str; + str.Format(L"%f", 1.12345); + EXPECT_EQ(L"1.123450", str); + } + + { + WideString str; + str.Format(L"%-1f", 1.12345); + EXPECT_EQ(L"1.123450", str); + } + + { + WideString str; + str.Format(L"%0f", 1.12345); + EXPECT_EQ(L"1.123450", str); + } + + { + WideString str; + str.Format(L"%.1048576f", 1.2); + EXPECT_EQ(L"", str); + } +} + +TEST(WideString, FormatOutOfRangeChar) { + WideString str; + str.Format(L"unsupported char '%c'", 0x00FF00FF); +} + +TEST(WideString, Empty) { + WideString empty_str; + EXPECT_TRUE(empty_str.IsEmpty()); + EXPECT_EQ(0u, empty_str.GetLength()); + const wchar_t* cstr = empty_str.c_str(); + EXPECT_EQ(0u, FXSYS_wcslen(cstr)); +} + +TEST(CFX_WidString, InitializerList) { + WideString many_str({L"clams", L" and ", L"oysters"}); + EXPECT_EQ(L"clams and oysters", many_str); + many_str = {L"fish", L" and ", L"chips", L" and ", L"soda"}; + EXPECT_EQ(L"fish and chips and soda", many_str); +} + +TEST(WideString, NullIterator) { + WideString null_str; + int32_t sum = 0; + bool any_present = false; + for (const auto& c : null_str) { + sum += c; // Avoid unused arg warnings. + any_present = true; + } + EXPECT_FALSE(any_present); + EXPECT_EQ(0, sum); +} + +TEST(WideString, EmptyIterator) { + WideString empty_str(L""); + int32_t sum = 0; + bool any_present = false; + for (const auto& c : empty_str) { + any_present = true; + sum += c; // Avoid unused arg warnings. + } + EXPECT_FALSE(any_present); + EXPECT_EQ(0, sum); +} + +TEST(WideString, OneCharIterator) { + WideString one_str(L"a"); + int32_t sum = 0; + bool any_present = false; + for (const auto& c : one_str) { + any_present = true; + sum += c; // Avoid unused arg warnings. + } + EXPECT_TRUE(any_present); + EXPECT_EQ(static_cast(L'a'), sum); +} + +TEST(WideString, MultiCharIterator) { + WideString one_str(L"abc"); + int32_t sum = 0; + bool any_present = false; + for (const auto& c : one_str) { + any_present = true; + sum += c; // Avoid unused arg warnings. + } + EXPECT_TRUE(any_present); + EXPECT_EQ(static_cast(L'a' + L'b' + L'c'), sum); +} + +TEST(WideString, AnyAllNoneOf) { + WideString str(L"aaaaaaaaaaaaaaaaab"); + EXPECT_FALSE(std::all_of(str.begin(), str.end(), + [](const wchar_t& c) { return c == L'a'; })); + + EXPECT_FALSE(std::none_of(str.begin(), str.end(), + [](const wchar_t& c) { return c == L'a'; })); + + EXPECT_TRUE(std::any_of(str.begin(), str.end(), + [](const wchar_t& c) { return c == L'a'; })); + + EXPECT_TRUE(pdfium::ContainsValue(str, L'a')); + EXPECT_TRUE(pdfium::ContainsValue(str, L'b')); + EXPECT_FALSE(pdfium::ContainsValue(str, L'z')); +} + +TEST(WideString, OStreamOverload) { + std::ostringstream stream; + + // Basic case, empty string + WideString str; + stream << str; + EXPECT_EQ("", stream.str()); + + // Basic case, wide character + str = L"\u20AC"; + stream << str; + EXPECT_EQ("\u20AC", stream.str()); + + // Basic case, non-empty string + str = L"def"; + stream.str(""); + stream << "abc" << str << "ghi"; + EXPECT_EQ("abcdefghi", stream.str()); + + // Changing the WideString does not change the stream it was written to. + str = L"123"; + EXPECT_EQ("abcdefghi", stream.str()); + + // Writing it again to the stream will use the latest value. + stream.str(""); + stream << "abc" << str << "ghi"; + EXPECT_EQ("abc123ghi", stream.str()); + + wchar_t stringWithNulls[]{'x', 'y', '\0', 'z'}; + + // Writing a WideString with nulls and no specified length treats it as + // a C-style null-terminated string. + str = WideString(stringWithNulls); + EXPECT_EQ(2u, str.GetLength()); + stream.str(""); + stream << str; + EXPECT_EQ(2u, stream.tellp()); + + // Writing a WideString with nulls but specifying its length treats it as + // a C++-style string. + str = WideString(stringWithNulls, 4); + EXPECT_EQ(4u, str.GetLength()); + stream.str(""); + stream << str; + EXPECT_EQ(4u, stream.tellp()); + + // << operators can be chained. + WideString str1(L"abc"); + WideString str2(L"def"); + stream.str(""); + stream << str1 << str2; + EXPECT_EQ("abcdef", stream.str()); +} + +TEST(WideString, WideOStreamOverload) { + std::wostringstream stream; + + // Basic case, empty string + WideString str; + stream << str; + EXPECT_EQ(L"", stream.str()); + + // Basic case, wide character + str = L"\u20AC"; + stream << str; + EXPECT_EQ(L"\u20AC", stream.str()); + + // Basic case, non-empty string + str = L"def"; + stream.str(L""); + stream << L"abc" << str << L"ghi"; + EXPECT_EQ(L"abcdefghi", stream.str()); + + // Changing the WideString does not change the stream it was written to. + str = L"123"; + EXPECT_EQ(L"abcdefghi", stream.str()); + + // Writing it again to the stream will use the latest value. + stream.str(L""); + stream << L"abc" << str << L"ghi"; + EXPECT_EQ(L"abc123ghi", stream.str()); + + wchar_t stringWithNulls[]{'x', 'y', '\0', 'z'}; + + // Writing a WideString with nulls and no specified length treats it as + // a C-style null-terminated string. + str = WideString(stringWithNulls); + EXPECT_EQ(2u, str.GetLength()); + stream.str(L""); + stream << str; + EXPECT_EQ(2u, stream.tellp()); + + // Writing a WideString with nulls but specifying its length treats it as + // a C++-style string. + str = WideString(stringWithNulls, 4); + EXPECT_EQ(4u, str.GetLength()); + stream.str(L""); + stream << str; + EXPECT_EQ(4u, stream.tellp()); + + // << operators can be chained. + WideString str1(L"abc"); + WideString str2(L"def"); + stream.str(L""); + stream << str1 << str2; + EXPECT_EQ(L"abcdef", stream.str()); +} + +TEST(WideStringView, OStreamOverload) { + // Basic case, empty string + { + std::ostringstream stream; + WideStringView str; + stream << str; + EXPECT_EQ("", stream.str()); + } + + // Basic case, non-empty string + { + std::ostringstream stream; + WideStringView str(L"def"); + stream << "abc" << str << "ghi"; + EXPECT_EQ("abcdefghi", stream.str()); + } + + // Basic case, wide character + { + std::ostringstream stream; + WideStringView str(L"\u20AC"); + stream << str; + EXPECT_EQ("\u20AC", stream.str()); + } + + // Changing the WideStringView does not change the stream it was written to. + { + std::ostringstream stream; + WideStringView str(L"abc"); + stream << str; + str = L"123"; + EXPECT_EQ("abc", stream.str()); + } + + // Writing it again to the stream will use the latest value. + { + std::ostringstream stream; + WideStringView str(L"abc"); + stream << str; + stream.str(""); + str = L"123"; + stream << str; + EXPECT_EQ("123", stream.str()); + } + + // Writing a WideStringView with nulls and no specified length treats it as + // a C-style null-terminated string. + { + wchar_t stringWithNulls[]{'x', 'y', '\0', 'z'}; + std::ostringstream stream; + WideStringView str(stringWithNulls); + EXPECT_EQ(2u, str.GetLength()); + stream << str; + EXPECT_EQ(2u, stream.tellp()); + str = L""; + } + + // Writing a WideStringView with nulls but specifying its length treats it as + // a C++-style string. + { + wchar_t stringWithNulls[]{'x', 'y', '\0', 'z'}; + std::ostringstream stream; + WideStringView str(stringWithNulls, 4); + EXPECT_EQ(4u, str.GetLength()); + stream << str; + EXPECT_EQ(4u, stream.tellp()); + str = L""; + } + + // << operators can be chained. + { + std::ostringstream stream; + WideStringView str1(L"abc"); + WideStringView str2(L"def"); + stream << str1 << str2; + EXPECT_EQ("abcdef", stream.str()); + } +} + +TEST(WideStringView, WideOStreamOverload) { + // Basic case, empty string + { + std::wostringstream stream; + WideStringView str; + stream << str; + EXPECT_EQ(L"", stream.str()); + } + + // Basic case, non-empty string + { + std::wostringstream stream; + WideStringView str(L"def"); + stream << "abc" << str << "ghi"; + EXPECT_EQ(L"abcdefghi", stream.str()); + } + + // Basic case, wide character + { + std::wostringstream stream; + WideStringView str(L"\u20AC"); + stream << str; + EXPECT_EQ(L"\u20AC", stream.str()); + } + + // Changing the WideStringView does not change the stream it was written to. + { + std::wostringstream stream; + WideStringView str(L"abc"); + stream << str; + str = L"123"; + EXPECT_EQ(L"abc", stream.str()); + } + + // Writing it again to the stream will use the latest value. + { + std::wostringstream stream; + WideStringView str(L"abc"); + stream << str; + stream.str(L""); + str = L"123"; + stream << str; + EXPECT_EQ(L"123", stream.str()); + } + + // Writing a WideStringView with nulls and no specified length treats it as + // a C-style null-terminated string. + { + wchar_t stringWithNulls[]{'x', 'y', '\0', 'z'}; + std::wostringstream stream; + WideStringView str(stringWithNulls); + EXPECT_EQ(2u, str.GetLength()); + stream << str; + EXPECT_EQ(2u, stream.tellp()); + } + + // Writing a WideStringView with nulls but specifying its length treats it as + // a C++-style string. + { + wchar_t stringWithNulls[]{'x', 'y', '\0', 'z'}; + std::wostringstream stream; + WideStringView str(stringWithNulls, 4); + EXPECT_EQ(4u, str.GetLength()); + stream << str; + EXPECT_EQ(4u, stream.tellp()); + } + + // << operators can be chained. + { + std::wostringstream stream; + WideStringView str1(L"abc"); + WideStringView str2(L"def"); + stream << str1 << str2; + EXPECT_EQ(L"abcdef", stream.str()); + } +} diff --git a/core/fxcrt/xml/cfx_saxcontext.h b/core/fxcrt/xml/cfx_saxcontext.h index f66c76c9cc..d4d74a385b 100644 --- a/core/fxcrt/xml/cfx_saxcontext.h +++ b/core/fxcrt/xml/cfx_saxcontext.h @@ -18,7 +18,7 @@ class CFX_SAXContext { ~CFX_SAXContext(); std::ostringstream m_TextBuf; - CFX_ByteString m_bsTagName; + ByteString m_bsTagName; CFX_SAXItem::Type m_eNode; }; diff --git a/core/fxcrt/xml/cfx_saxreader.cpp b/core/fxcrt/xml/cfx_saxreader.cpp index 641dc08688..e2c09d14cc 100644 --- a/core/fxcrt/xml/cfx_saxreader.cpp +++ b/core/fxcrt/xml/cfx_saxreader.cpp @@ -293,8 +293,8 @@ void CFX_SAXReader::ParseChar(uint8_t ch) { m_iEntityStart = -1; // NOTE: Relies on negative lengths being treated as empty strings. - CFX_ByteString csEntity(m_Data.data() + iSaveStart + 1, - CurrentDataIndex() - iSaveStart - 1); + ByteString csEntity(m_Data.data() + iSaveStart + 1, + CurrentDataIndex() - iSaveStart - 1); int32_t iLen = csEntity.GetLength(); if (iLen == 0) return; @@ -649,7 +649,7 @@ void CFX_SAXReader::NotifyData() { m_pHandler->OnTagData( pItem->m_pNode, m_bCharData ? CFX_SAXItem::Type::CharData : CFX_SAXItem::Type::Text, - CFX_ByteStringC(m_Data), m_File.m_dwCur + m_dwDataOffset); + ByteStringView(m_Data), m_File.m_dwCur + m_dwDataOffset); } void CFX_SAXReader::NotifyEnter() { @@ -662,7 +662,7 @@ void CFX_SAXReader::NotifyEnter() { if (pItem->m_eNode == CFX_SAXItem::Type::Tag || pItem->m_eNode == CFX_SAXItem::Type::Instruction) { - pItem->m_pNode = m_pHandler->OnTagEnter(CFX_ByteStringC(m_Data), + pItem->m_pNode = m_pHandler->OnTagEnter(ByteStringView(m_Data), pItem->m_eNode, m_dwNodePos); } } @@ -677,8 +677,8 @@ void CFX_SAXReader::NotifyAttribute() { if (pItem->m_eNode == CFX_SAXItem::Type::Tag || pItem->m_eNode == CFX_SAXItem::Type::Instruction) { - m_pHandler->OnTagAttribute(pItem->m_pNode, CFX_ByteStringC(m_Name), - CFX_ByteStringC(m_Data)); + m_pHandler->OnTagAttribute(pItem->m_pNode, ByteStringView(m_Name), + ByteStringView(m_Data)); } } @@ -717,7 +717,7 @@ void CFX_SAXReader::NotifyEnd() { return; if (pItem->m_eNode == CFX_SAXItem::Type::Tag) - m_pHandler->OnTagEnd(pItem->m_pNode, CFX_ByteStringC(m_Data), m_dwNodePos); + m_pHandler->OnTagEnd(pItem->m_pNode, ByteStringView(m_Data), m_dwNodePos); } void CFX_SAXReader::NotifyTargetData() { @@ -730,10 +730,10 @@ void CFX_SAXReader::NotifyTargetData() { if (pItem->m_eNode == CFX_SAXItem::Type::Instruction) { m_pHandler->OnTargetData(pItem->m_pNode, pItem->m_eNode, - CFX_ByteStringC(m_Name), m_dwNodePos); + ByteStringView(m_Name), m_dwNodePos); } else if (pItem->m_eNode == CFX_SAXItem::Type::Comment) { m_pHandler->OnTargetData(pItem->m_pNode, pItem->m_eNode, - CFX_ByteStringC(m_Data), m_dwNodePos); + ByteStringView(m_Data), m_dwNodePos); } } diff --git a/core/fxcrt/xml/cfx_saxreader.h b/core/fxcrt/xml/cfx_saxreader.h index 3db1c7c80c..51d9e43121 100644 --- a/core/fxcrt/xml/cfx_saxreader.h +++ b/core/fxcrt/xml/cfx_saxreader.h @@ -75,24 +75,24 @@ class CFX_SAXReader { class HandlerIface { public: virtual ~HandlerIface() {} - virtual CFX_SAXContext* OnTagEnter(const CFX_ByteStringC& bsTagName, + virtual CFX_SAXContext* OnTagEnter(const ByteStringView& bsTagName, CFX_SAXItem::Type eType, uint32_t dwStartPos) = 0; virtual void OnTagAttribute(CFX_SAXContext* pTag, - const CFX_ByteStringC& bsAttri, - const CFX_ByteStringC& bsValue) = 0; + const ByteStringView& bsAttri, + const ByteStringView& bsValue) = 0; virtual void OnTagBreak(CFX_SAXContext* pTag) = 0; virtual void OnTagData(CFX_SAXContext* pTag, CFX_SAXItem::Type eType, - const CFX_ByteStringC& bsData, + const ByteStringView& bsData, uint32_t dwStartPos) = 0; virtual void OnTagClose(CFX_SAXContext* pTag, uint32_t dwEndPos) = 0; virtual void OnTagEnd(CFX_SAXContext* pTag, - const CFX_ByteStringC& bsTagName, + const ByteStringView& bsTagName, uint32_t dwEndPos) = 0; virtual void OnTargetData(CFX_SAXContext* pTag, CFX_SAXItem::Type eType, - const CFX_ByteStringC& bsData, + const ByteStringView& bsData, uint32_t dwStartPos) = 0; }; diff --git a/core/fxcrt/xml/cfx_saxreader_unittest.cpp b/core/fxcrt/xml/cfx_saxreader_unittest.cpp index 62828500c9..13d06325a7 100644 --- a/core/fxcrt/xml/cfx_saxreader_unittest.cpp +++ b/core/fxcrt/xml/cfx_saxreader_unittest.cpp @@ -17,28 +17,28 @@ namespace { class MockHandler : public CFX_SAXReader::HandlerIface { public: MOCK_METHOD3(OnTagEnter, - CFX_SAXContext*(const CFX_ByteStringC& bsTagName, + CFX_SAXContext*(const ByteStringView& bsTagName, CFX_SAXItem::Type eType, uint32_t dwStartPos)); MOCK_METHOD3(OnTagAttribute, void(CFX_SAXContext* pTag, - const CFX_ByteStringC& bsAttri, - const CFX_ByteStringC& bsValue)); + const ByteStringView& bsAttri, + const ByteStringView& bsValue)); MOCK_METHOD1(OnTagBreak, void(CFX_SAXContext* pTag)); MOCK_METHOD4(OnTagData, void(CFX_SAXContext* pTag, CFX_SAXItem::Type eType, - const CFX_ByteStringC& bsData, + const ByteStringView& bsData, uint32_t dwStartPos)); MOCK_METHOD2(OnTagClose, void(CFX_SAXContext* pTag, uint32_t dwEndPos)); MOCK_METHOD3(OnTagEnd, void(CFX_SAXContext* pTag, - const CFX_ByteStringC& bsTagName, + const ByteStringView& bsTagName, uint32_t dwEndPos)); MOCK_METHOD4(OnTargetData, void(CFX_SAXContext* pTag, CFX_SAXItem::Type eType, - const CFX_ByteStringC& bsData, + const ByteStringView& bsData, uint32_t dwStartPos)); }; diff --git a/core/fxcrt/xml/cfx_saxreaderhandler.cpp b/core/fxcrt/xml/cfx_saxreaderhandler.cpp index b8399ff5cc..d255ce924d 100644 --- a/core/fxcrt/xml/cfx_saxreaderhandler.cpp +++ b/core/fxcrt/xml/cfx_saxreaderhandler.cpp @@ -18,7 +18,7 @@ CFX_SAXReaderHandler::CFX_SAXReaderHandler(CFX_ChecksumContext* pContext) CFX_SAXReaderHandler::~CFX_SAXReaderHandler() {} CFX_SAXContext* CFX_SAXReaderHandler::OnTagEnter( - const CFX_ByteStringC& bsTagName, + const ByteStringView& bsTagName, CFX_SAXItem::Type eType, uint32_t dwStartPos) { UpdateChecksum(true); @@ -38,8 +38,8 @@ CFX_SAXContext* CFX_SAXReaderHandler::OnTagEnter( } void CFX_SAXReaderHandler::OnTagAttribute(CFX_SAXContext* pTag, - const CFX_ByteStringC& bsAttri, - const CFX_ByteStringC& bsValue) { + const ByteStringView& bsAttri, + const ByteStringView& bsValue) { if (!pTag) return; pTag->m_TextBuf << " " << bsAttri << "=\"" << bsValue << "\""; @@ -55,7 +55,7 @@ void CFX_SAXReaderHandler::OnTagBreak(CFX_SAXContext* pTag) { void CFX_SAXReaderHandler::OnTagData(CFX_SAXContext* pTag, CFX_SAXItem::Type eType, - const CFX_ByteStringC& bsData, + const ByteStringView& bsData, uint32_t dwStartPos) { if (!pTag) return; @@ -75,13 +75,13 @@ void CFX_SAXReaderHandler::OnTagClose(CFX_SAXContext* pTag, uint32_t dwEndPos) { if (pTag->m_eNode == CFX_SAXItem::Type::Instruction) pTag->m_TextBuf << "?>"; else if (pTag->m_eNode == CFX_SAXItem::Type::Tag) - pTag->m_TextBuf << ">m_bsTagName.AsStringC() << ">"; + pTag->m_TextBuf << ">m_bsTagName.AsStringView() << ">"; UpdateChecksum(false); } void CFX_SAXReaderHandler::OnTagEnd(CFX_SAXContext* pTag, - const CFX_ByteStringC& bsTagName, + const ByteStringView& bsTagName, uint32_t dwEndPos) { if (!pTag) return; @@ -92,7 +92,7 @@ void CFX_SAXReaderHandler::OnTagEnd(CFX_SAXContext* pTag, void CFX_SAXReaderHandler::OnTargetData(CFX_SAXContext* pTag, CFX_SAXItem::Type eType, - const CFX_ByteStringC& bsData, + const ByteStringView& bsData, uint32_t dwStartPos) { if (!pTag && eType != CFX_SAXItem::Type::Comment) return; @@ -122,7 +122,7 @@ void CFX_SAXReaderHandler::UpdateChecksum(bool bCheckSpace) { } } if (bUpdata) - m_pContext->Update(CFX_ByteStringC(pBuffer, iLength)); + m_pContext->Update(ByteStringView(pBuffer, iLength)); m_SAXContext.m_TextBuf.str(""); } diff --git a/core/fxcrt/xml/cfx_saxreaderhandler.h b/core/fxcrt/xml/cfx_saxreaderhandler.h index c5e1dc28b6..263008f1ff 100644 --- a/core/fxcrt/xml/cfx_saxreaderhandler.h +++ b/core/fxcrt/xml/cfx_saxreaderhandler.h @@ -18,24 +18,24 @@ class CFX_SAXReaderHandler : public CFX_SAXReader::HandlerIface { explicit CFX_SAXReaderHandler(CFX_ChecksumContext* pContext); ~CFX_SAXReaderHandler() override; - CFX_SAXContext* OnTagEnter(const CFX_ByteStringC& bsTagName, + CFX_SAXContext* OnTagEnter(const ByteStringView& bsTagName, CFX_SAXItem::Type eType, uint32_t dwStartPos) override; void OnTagAttribute(CFX_SAXContext* pTag, - const CFX_ByteStringC& bsAttri, - const CFX_ByteStringC& bsValue) override; + const ByteStringView& bsAttri, + const ByteStringView& bsValue) override; void OnTagBreak(CFX_SAXContext* pTag) override; void OnTagData(CFX_SAXContext* pTag, CFX_SAXItem::Type eType, - const CFX_ByteStringC& bsData, + const ByteStringView& bsData, uint32_t dwStartPos) override; void OnTagClose(CFX_SAXContext* pTag, uint32_t dwEndPos) override; void OnTagEnd(CFX_SAXContext* pTag, - const CFX_ByteStringC& bsTagName, + const ByteStringView& bsTagName, uint32_t dwEndPos) override; void OnTargetData(CFX_SAXContext* pTag, CFX_SAXItem::Type eType, - const CFX_ByteStringC& bsData, + const ByteStringView& bsData, uint32_t dwStartPos) override; private: diff --git a/core/fxcrt/xml/cfx_xmlattributenode.cpp b/core/fxcrt/xml/cfx_xmlattributenode.cpp index 9ea6756839..6104747793 100644 --- a/core/fxcrt/xml/cfx_xmlattributenode.cpp +++ b/core/fxcrt/xml/cfx_xmlattributenode.cpp @@ -8,28 +8,27 @@ #include "core/fxcrt/fx_extension.h" -CFX_XMLAttributeNode::CFX_XMLAttributeNode(const CFX_WideString& name) +CFX_XMLAttributeNode::CFX_XMLAttributeNode(const WideString& name) : CFX_XMLNode(), name_(name) { ASSERT(name_.GetLength() > 0); } CFX_XMLAttributeNode::~CFX_XMLAttributeNode() {} -bool CFX_XMLAttributeNode::HasAttribute(const CFX_WideString& name) const { +bool CFX_XMLAttributeNode::HasAttribute(const WideString& name) const { return attrs_.find(name) != attrs_.end(); } -CFX_WideString CFX_XMLAttributeNode::GetString( - const CFX_WideString& name) const { +WideString CFX_XMLAttributeNode::GetString(const WideString& name) const { auto it = attrs_.find(name); - return it != attrs_.end() ? it->second : CFX_WideString(); + return it != attrs_.end() ? it->second : WideString(); } -void CFX_XMLAttributeNode::SetString(const CFX_WideString& name, - const CFX_WideString& value) { +void CFX_XMLAttributeNode::SetString(const WideString& name, + const WideString& value) { attrs_[name] = value; } -void CFX_XMLAttributeNode::RemoveAttribute(const CFX_WideString& name) { +void CFX_XMLAttributeNode::RemoveAttribute(const WideString& name) { attrs_.erase(name); } diff --git a/core/fxcrt/xml/cfx_xmlattributenode.h b/core/fxcrt/xml/cfx_xmlattributenode.h index e8f358eb59..1ac9b84db2 100644 --- a/core/fxcrt/xml/cfx_xmlattributenode.h +++ b/core/fxcrt/xml/cfx_xmlattributenode.h @@ -15,30 +15,30 @@ class CFX_XMLAttributeNode : public CFX_XMLNode { public: - explicit CFX_XMLAttributeNode(const CFX_WideString& name); + explicit CFX_XMLAttributeNode(const WideString& name); ~CFX_XMLAttributeNode() override; // CFX_XMLNode FX_XMLNODETYPE GetType() const override = 0; std::unique_ptr Clone() override = 0; - CFX_WideString GetName() const { return name_; } - const std::map& GetAttributes() const { + WideString GetName() const { return name_; } + const std::map& GetAttributes() const { return attrs_; } - void SetAttributes(const std::map& attrs) { + void SetAttributes(const std::map& attrs) { attrs_ = attrs; } - bool HasAttribute(const CFX_WideString& name) const; + bool HasAttribute(const WideString& name) const; - void SetString(const CFX_WideString& name, const CFX_WideString& value); - CFX_WideString GetString(const CFX_WideString& name) const; + void SetString(const WideString& name, const WideString& value); + WideString GetString(const WideString& name) const; - void RemoveAttribute(const CFX_WideString& name); + void RemoveAttribute(const WideString& name); private: - CFX_WideString name_; - std::map attrs_; + WideString name_; + std::map attrs_; }; #endif // CORE_FXCRT_XML_CFX_XMLATTRIBUTENODE_H_ diff --git a/core/fxcrt/xml/cfx_xmlchardata.cpp b/core/fxcrt/xml/cfx_xmlchardata.cpp index 185bd064df..902d139c99 100644 --- a/core/fxcrt/xml/cfx_xmlchardata.cpp +++ b/core/fxcrt/xml/cfx_xmlchardata.cpp @@ -8,7 +8,7 @@ #include "third_party/base/ptr_util.h" -CFX_XMLCharData::CFX_XMLCharData(const CFX_WideString& wsCData) +CFX_XMLCharData::CFX_XMLCharData(const WideString& wsCData) : CFX_XMLText(wsCData) {} CFX_XMLCharData::~CFX_XMLCharData() {} diff --git a/core/fxcrt/xml/cfx_xmlchardata.h b/core/fxcrt/xml/cfx_xmlchardata.h index c5c007be90..9a4710fa51 100644 --- a/core/fxcrt/xml/cfx_xmlchardata.h +++ b/core/fxcrt/xml/cfx_xmlchardata.h @@ -14,7 +14,7 @@ class CFX_XMLCharData : public CFX_XMLText { public: - explicit CFX_XMLCharData(const CFX_WideString& wsCData); + explicit CFX_XMLCharData(const WideString& wsCData); ~CFX_XMLCharData() override; FX_XMLNODETYPE GetType() const override; diff --git a/core/fxcrt/xml/cfx_xmldoc.cpp b/core/fxcrt/xml/cfx_xmldoc.cpp index 6fce38cea6..e9a09b761b 100644 --- a/core/fxcrt/xml/cfx_xmldoc.cpp +++ b/core/fxcrt/xml/cfx_xmldoc.cpp @@ -53,7 +53,7 @@ void CFX_XMLDoc::SaveXMLNode( CFX_XMLNode* pNode = (CFX_XMLNode*)pINode; switch (pNode->GetType()) { case FX_XMLNODE_Instruction: { - CFX_WideString ws; + WideString ws; CFX_XMLInstruction* pInstruction = (CFX_XMLInstruction*)pNode; if (pInstruction->GetName().CompareNoCase(L"xml") == 0) { ws = L""; - pXMLStream->WriteString(ws.AsStringC()); + pXMLStream->WriteString(ws.AsStringView()); } else { ws.Format(L"GetName().c_str()); - pXMLStream->WriteString(ws.AsStringC()); + pXMLStream->WriteString(ws.AsStringView()); for (auto it : pInstruction->GetAttributes()) { - CFX_WideString wsValue = it.second; + WideString wsValue = it.second; wsValue.Replace(L"&", L"&"); wsValue.Replace(L"<", L"<"); wsValue.Replace(L">", L">"); @@ -84,28 +84,28 @@ void CFX_XMLDoc::SaveXMLNode( ws += L"=\""; ws += wsValue; ws += L"\""; - pXMLStream->WriteString(ws.AsStringC()); + pXMLStream->WriteString(ws.AsStringView()); } for (auto target : pInstruction->GetTargetData()) { ws = L" \""; ws += target; ws += L"\""; - pXMLStream->WriteString(ws.AsStringC()); + pXMLStream->WriteString(ws.AsStringView()); } ws = L"?>"; - pXMLStream->WriteString(ws.AsStringC()); + pXMLStream->WriteString(ws.AsStringView()); } break; } case FX_XMLNODE_Element: { - CFX_WideString ws; + WideString ws; ws = L"<"; ws += static_cast(pNode)->GetName(); - pXMLStream->WriteString(ws.AsStringC()); + pXMLStream->WriteString(ws.AsStringView()); for (auto it : static_cast(pNode)->GetAttributes()) { - CFX_WideString wsValue = it.second; + WideString wsValue = it.second; wsValue.Replace(L"&", L"&"); wsValue.Replace(L"<", L"<"); wsValue.Replace(L">", L">"); @@ -117,11 +117,11 @@ void CFX_XMLDoc::SaveXMLNode( ws += L"=\""; ws += wsValue; ws += L"\""; - pXMLStream->WriteString(ws.AsStringC()); + pXMLStream->WriteString(ws.AsStringView()); } if (pNode->m_pChild) { ws = L"\n>"; - pXMLStream->WriteString(ws.AsStringC()); + pXMLStream->WriteString(ws.AsStringView()); CFX_XMLNode* pChild = pNode->m_pChild; while (pChild) { SaveXMLNode(pXMLStream, static_cast(pChild)); @@ -133,24 +133,24 @@ void CFX_XMLDoc::SaveXMLNode( } else { ws = L"\n/>"; } - pXMLStream->WriteString(ws.AsStringC()); + pXMLStream->WriteString(ws.AsStringView()); break; } case FX_XMLNODE_Text: { - CFX_WideString ws = static_cast(pNode)->GetText(); + WideString ws = static_cast(pNode)->GetText(); ws.Replace(L"&", L"&"); ws.Replace(L"<", L"<"); ws.Replace(L">", L">"); ws.Replace(L"\'", L"'"); ws.Replace(L"\"", L"""); - pXMLStream->WriteString(ws.AsStringC()); + pXMLStream->WriteString(ws.AsStringView()); break; } case FX_XMLNODE_CharData: { - CFX_WideString ws = L"(pNode)->GetText(); ws += L"]]>"; - pXMLStream->WriteString(ws.AsStringC()); + pXMLStream->WriteString(ws.AsStringView()); break; } case FX_XMLNODE_Unknown: diff --git a/core/fxcrt/xml/cfx_xmlelement.cpp b/core/fxcrt/xml/cfx_xmlelement.cpp index 5b5fe45561..1317e9a72b 100644 --- a/core/fxcrt/xml/cfx_xmlelement.cpp +++ b/core/fxcrt/xml/cfx_xmlelement.cpp @@ -15,7 +15,7 @@ #include "third_party/base/ptr_util.h" #include "third_party/base/stl_util.h" -CFX_XMLElement::CFX_XMLElement(const CFX_WideString& wsTag) +CFX_XMLElement::CFX_XMLElement(const WideString& wsTag) : CFX_XMLAttributeNode(wsTag) {} CFX_XMLElement::~CFX_XMLElement() {} @@ -28,7 +28,7 @@ std::unique_ptr CFX_XMLElement::Clone() { auto pClone = pdfium::MakeUnique(GetName()); pClone->SetAttributes(GetAttributes()); - CFX_WideString wsText; + WideString wsText; CFX_XMLNode* pChild = m_pChild; while (pChild) { switch (pChild->GetType()) { @@ -44,21 +44,21 @@ std::unique_ptr CFX_XMLElement::Clone() { return std::move(pClone); } -CFX_WideString CFX_XMLElement::GetLocalTagName() const { +WideString CFX_XMLElement::GetLocalTagName() const { auto pos = GetName().Find(L':'); return pos.has_value() ? GetName().Right(GetName().GetLength() - pos.value() - 1) : GetName(); } -CFX_WideString CFX_XMLElement::GetNamespacePrefix() const { +WideString CFX_XMLElement::GetNamespacePrefix() const { auto pos = GetName().Find(L':'); - return pos.has_value() ? GetName().Left(pos.value()) : CFX_WideString(); + return pos.has_value() ? GetName().Left(pos.value()) : WideString(); } -CFX_WideString CFX_XMLElement::GetNamespaceURI() const { - CFX_WideString wsAttri(L"xmlns"); - CFX_WideString wsPrefix = GetNamespacePrefix(); +WideString CFX_XMLElement::GetNamespaceURI() const { + WideString wsAttri(L"xmlns"); + WideString wsPrefix = GetNamespacePrefix(); if (wsPrefix.GetLength() > 0) { wsAttri += L":"; wsAttri += wsPrefix; @@ -76,10 +76,10 @@ CFX_WideString CFX_XMLElement::GetNamespaceURI() const { } return pElement->GetString(wsAttri); } - return CFX_WideString(); + return WideString(); } -CFX_WideString CFX_XMLElement::GetTextData() const { +WideString CFX_XMLElement::GetTextData() const { CFX_WideTextBuf buffer; CFX_XMLNode* pChild = m_pChild; while (pChild) { @@ -96,7 +96,7 @@ CFX_WideString CFX_XMLElement::GetTextData() const { return buffer.MakeString(); } -void CFX_XMLElement::SetTextData(const CFX_WideString& wsText) { +void CFX_XMLElement::SetTextData(const WideString& wsText) { if (wsText.GetLength() < 1) return; InsertChildNode(new CFX_XMLText(wsText)); diff --git a/core/fxcrt/xml/cfx_xmlelement.h b/core/fxcrt/xml/cfx_xmlelement.h index 20780342af..59e3af6a44 100644 --- a/core/fxcrt/xml/cfx_xmlelement.h +++ b/core/fxcrt/xml/cfx_xmlelement.h @@ -15,19 +15,19 @@ class CFX_XMLElement : public CFX_XMLAttributeNode { public: - explicit CFX_XMLElement(const CFX_WideString& wsTag); + explicit CFX_XMLElement(const WideString& wsTag); ~CFX_XMLElement() override; // CFX_XMLNode FX_XMLNODETYPE GetType() const override; std::unique_ptr Clone() override; - CFX_WideString GetLocalTagName() const; - CFX_WideString GetNamespacePrefix() const; - CFX_WideString GetNamespaceURI() const; + WideString GetLocalTagName() const; + WideString GetNamespacePrefix() const; + WideString GetNamespaceURI() const; - CFX_WideString GetTextData() const; - void SetTextData(const CFX_WideString& wsText); + WideString GetTextData() const; + void SetTextData(const WideString& wsText); }; #endif // CORE_FXCRT_XML_CFX_XMLELEMENT_H_ diff --git a/core/fxcrt/xml/cfx_xmlinstruction.cpp b/core/fxcrt/xml/cfx_xmlinstruction.cpp index 3c7deda92a..75a4a2eec6 100644 --- a/core/fxcrt/xml/cfx_xmlinstruction.cpp +++ b/core/fxcrt/xml/cfx_xmlinstruction.cpp @@ -12,7 +12,7 @@ #include "third_party/base/ptr_util.h" #include "third_party/base/stl_util.h" -CFX_XMLInstruction::CFX_XMLInstruction(const CFX_WideString& wsTarget) +CFX_XMLInstruction::CFX_XMLInstruction(const WideString& wsTarget) : CFX_XMLAttributeNode(wsTarget) {} CFX_XMLInstruction::~CFX_XMLInstruction() {} @@ -28,7 +28,7 @@ std::unique_ptr CFX_XMLInstruction::Clone() { return std::move(pClone); } -void CFX_XMLInstruction::AppendData(const CFX_WideString& wsData) { +void CFX_XMLInstruction::AppendData(const WideString& wsData) { m_TargetData.push_back(wsData); } diff --git a/core/fxcrt/xml/cfx_xmlinstruction.h b/core/fxcrt/xml/cfx_xmlinstruction.h index 99554fc239..ff27dae3a4 100644 --- a/core/fxcrt/xml/cfx_xmlinstruction.h +++ b/core/fxcrt/xml/cfx_xmlinstruction.h @@ -15,21 +15,19 @@ class CFX_XMLInstruction : public CFX_XMLAttributeNode { public: - explicit CFX_XMLInstruction(const CFX_WideString& wsTarget); + explicit CFX_XMLInstruction(const WideString& wsTarget); ~CFX_XMLInstruction() override; // CFX_XMLNode FX_XMLNODETYPE GetType() const override; std::unique_ptr Clone() override; - const std::vector& GetTargetData() const { - return m_TargetData; - } - void AppendData(const CFX_WideString& wsData); + const std::vector& GetTargetData() const { return m_TargetData; } + void AppendData(const WideString& wsData); void RemoveData(int32_t index); private: - std::vector m_TargetData; + std::vector m_TargetData; }; #endif // CORE_FXCRT_XML_CFX_XMLINSTRUCTION_H_ diff --git a/core/fxcrt/xml/cfx_xmlnode.cpp b/core/fxcrt/xml/cfx_xmlnode.cpp index 47b3105f10..7a893af4a0 100644 --- a/core/fxcrt/xml/cfx_xmlnode.cpp +++ b/core/fxcrt/xml/cfx_xmlnode.cpp @@ -84,7 +84,7 @@ CFX_XMLNode* CFX_XMLNode::GetPath(const wchar_t* pPath, if (iLength == 0) { return nullptr; } - CFX_WideString csPath; + WideString csPath; const wchar_t* pStart = pPath; const wchar_t* pEnd = pPath + iLength; wchar_t ch; @@ -105,7 +105,7 @@ CFX_XMLNode* CFX_XMLNode::GetPath(const wchar_t* pPath, } else if (csPath.Compare(L".") == 0) { pFind = (CFX_XMLNode*)this; } else { - CFX_WideString wsTag; + WideString wsTag; CFX_XMLNode* pNode = m_pChild; while (pNode) { if (pNode->GetType() == FX_XMLNODE_Element) { @@ -334,7 +334,7 @@ void CFX_XMLNode::SaveXMLNode( CFX_XMLNode* pNode = (CFX_XMLNode*)this; switch (pNode->GetType()) { case FX_XMLNODE_Instruction: { - CFX_WideString ws; + WideString ws; CFX_XMLInstruction* pInstruction = (CFX_XMLInstruction*)pNode; if (pInstruction->GetName().CompareNoCase(L"xml") == 0) { ws = L""; - pXMLStream->WriteString(ws.AsStringC()); + pXMLStream->WriteString(ws.AsStringView()); } else { ws.Format(L"GetName().c_str()); - pXMLStream->WriteString(ws.AsStringC()); + pXMLStream->WriteString(ws.AsStringView()); for (auto it : pInstruction->GetAttributes()) { - CFX_WideString wsValue = it.second; + WideString wsValue = it.second; wsValue.Replace(L"&", L"&"); wsValue.Replace(L"<", L"<"); wsValue.Replace(L">", L">"); @@ -365,28 +365,28 @@ void CFX_XMLNode::SaveXMLNode( ws += L"=\""; ws += wsValue; ws += L"\""; - pXMLStream->WriteString(ws.AsStringC()); + pXMLStream->WriteString(ws.AsStringView()); } for (auto target : pInstruction->GetTargetData()) { ws = L" \""; ws += target; ws += L"\""; - pXMLStream->WriteString(ws.AsStringC()); + pXMLStream->WriteString(ws.AsStringView()); } ws = L"?>"; - pXMLStream->WriteString(ws.AsStringC()); + pXMLStream->WriteString(ws.AsStringView()); } break; } case FX_XMLNODE_Element: { - CFX_WideString ws; + WideString ws; ws = L"<"; ws += static_cast(pNode)->GetName(); - pXMLStream->WriteString(ws.AsStringC()); + pXMLStream->WriteString(ws.AsStringView()); for (auto it : static_cast(pNode)->GetAttributes()) { - CFX_WideString wsValue = it.second; + WideString wsValue = it.second; wsValue.Replace(L"&", L"&"); wsValue.Replace(L"<", L"<"); wsValue.Replace(L">", L">"); @@ -398,11 +398,11 @@ void CFX_XMLNode::SaveXMLNode( ws += L"=\""; ws += wsValue; ws += L"\""; - pXMLStream->WriteString(ws.AsStringC()); + pXMLStream->WriteString(ws.AsStringView()); } if (pNode->m_pChild) { ws = L"\n>"; - pXMLStream->WriteString(ws.AsStringC()); + pXMLStream->WriteString(ws.AsStringView()); CFX_XMLNode* pChild = pNode->m_pChild; while (pChild) { pChild->SaveXMLNode(pXMLStream); @@ -414,24 +414,24 @@ void CFX_XMLNode::SaveXMLNode( } else { ws = L"\n/>"; } - pXMLStream->WriteString(ws.AsStringC()); + pXMLStream->WriteString(ws.AsStringView()); break; } case FX_XMLNODE_Text: { - CFX_WideString ws = static_cast(pNode)->GetText(); + WideString ws = static_cast(pNode)->GetText(); ws.Replace(L"&", L"&"); ws.Replace(L"<", L"<"); ws.Replace(L">", L">"); ws.Replace(L"\'", L"'"); ws.Replace(L"\"", L"""); - pXMLStream->WriteString(ws.AsStringC()); + pXMLStream->WriteString(ws.AsStringView()); break; } case FX_XMLNODE_CharData: { - CFX_WideString ws = L"(pNode)->GetText(); ws += L"]]>"; - pXMLStream->WriteString(ws.AsStringC()); + pXMLStream->WriteString(ws.AsStringView()); break; } case FX_XMLNODE_Unknown: diff --git a/core/fxcrt/xml/cfx_xmlparser.cpp b/core/fxcrt/xml/cfx_xmlparser.cpp index ce45481512..280c06d3f1 100644 --- a/core/fxcrt/xml/cfx_xmlparser.cpp +++ b/core/fxcrt/xml/cfx_xmlparser.cpp @@ -101,7 +101,7 @@ int32_t CFX_XMLParser::DoParser() { m_pParent = m_pChild; if (m_dwCheckStatus != 0x03 && m_NodeStack.size() == 3) { - CFX_WideString wsTag = + WideString wsTag = static_cast(m_pChild)->GetLocalTagName(); if (wsTag == L"template") { m_dwCheckStatus |= 0x01; diff --git a/core/fxcrt/xml/cfx_xmlparser.h b/core/fxcrt/xml/cfx_xmlparser.h index 9746d78ae8..f98b658d9a 100644 --- a/core/fxcrt/xml/cfx_xmlparser.h +++ b/core/fxcrt/xml/cfx_xmlparser.h @@ -38,8 +38,8 @@ class CFX_XMLParser { CFX_XMLNode* m_pParent; CFX_XMLNode* m_pChild; std::stack m_NodeStack; - CFX_WideString m_ws1; - CFX_WideString m_ws2; + WideString m_ws1; + WideString m_ws2; FX_XmlSyntaxResult m_syntaxParserResult; }; diff --git a/core/fxcrt/xml/cfx_xmlsyntaxparser.cpp b/core/fxcrt/xml/cfx_xmlsyntaxparser.cpp index bbbc4f4399..d55985240d 100644 --- a/core/fxcrt/xml/cfx_xmlsyntaxparser.cpp +++ b/core/fxcrt/xml/cfx_xmlsyntaxparser.cpp @@ -623,7 +623,7 @@ void CFX_XMLSyntaxParser::ParseTextChar(wchar_t character) { m_pCurrentBlock[m_iIndexInBlock++] = character; m_BlockBuffer.IncrementDataLength(); if (m_iEntityStart > -1 && character == L';') { - CFX_WideString csEntity = m_BlockBuffer.GetTextData( + WideString csEntity = m_BlockBuffer.GetTextData( m_iEntityStart + 1, m_BlockBuffer.GetDataLength() - 1 - m_iEntityStart - 1); int32_t iLen = csEntity.GetLength(); diff --git a/core/fxcrt/xml/cfx_xmlsyntaxparser.h b/core/fxcrt/xml/cfx_xmlsyntaxparser.h index c59cabae19..d3f4bf2edb 100644 --- a/core/fxcrt/xml/cfx_xmlsyntaxparser.h +++ b/core/fxcrt/xml/cfx_xmlsyntaxparser.h @@ -50,27 +50,27 @@ class CFX_XMLSyntaxParser { int32_t GetCurrentNodeNumber() const { return m_iCurrentNodeNum; } int32_t GetLastNodeNumber() const { return m_iLastNodeNum; } - CFX_WideString GetTargetName() const { + WideString GetTargetName() const { return m_BlockBuffer.GetTextData(0, m_iTextDataLength); } - CFX_WideString GetTagName() const { + WideString GetTagName() const { return m_BlockBuffer.GetTextData(0, m_iTextDataLength); } - CFX_WideString GetAttributeName() const { + WideString GetAttributeName() const { return m_BlockBuffer.GetTextData(0, m_iTextDataLength); } - CFX_WideString GetAttributeValue() const { + WideString GetAttributeValue() const { return m_BlockBuffer.GetTextData(0, m_iTextDataLength); } - CFX_WideString GetTextData() const { + WideString GetTextData() const { return m_BlockBuffer.GetTextData(0, m_iTextDataLength); } - CFX_WideString GetTargetData() const { + WideString GetTargetData() const { return m_BlockBuffer.GetTextData(0, m_iTextDataLength); } diff --git a/core/fxcrt/xml/cfx_xmltext.cpp b/core/fxcrt/xml/cfx_xmltext.cpp index 4c41fcd9f8..83ad0434bf 100644 --- a/core/fxcrt/xml/cfx_xmltext.cpp +++ b/core/fxcrt/xml/cfx_xmltext.cpp @@ -8,7 +8,7 @@ #include "third_party/base/ptr_util.h" -CFX_XMLText::CFX_XMLText(const CFX_WideString& wsText) +CFX_XMLText::CFX_XMLText(const WideString& wsText) : CFX_XMLNode(), m_wsText(wsText) {} CFX_XMLText::~CFX_XMLText() {} diff --git a/core/fxcrt/xml/cfx_xmltext.h b/core/fxcrt/xml/cfx_xmltext.h index 20fb858302..e9f35855f5 100644 --- a/core/fxcrt/xml/cfx_xmltext.h +++ b/core/fxcrt/xml/cfx_xmltext.h @@ -14,18 +14,18 @@ class CFX_XMLText : public CFX_XMLNode { public: - explicit CFX_XMLText(const CFX_WideString& wsText); + explicit CFX_XMLText(const WideString& wsText); ~CFX_XMLText() override; // CFX_XMLNode FX_XMLNODETYPE GetType() const override; std::unique_ptr Clone() override; - CFX_WideString GetText() const { return m_wsText; } - void SetText(const CFX_WideString& wsText) { m_wsText = wsText; } + WideString GetText() const { return m_wsText; } + void SetText(const WideString& wsText) { m_wsText = wsText; } private: - CFX_WideString m_wsText; + WideString m_wsText; }; #endif // CORE_FXCRT_XML_CFX_XMLTEXT_H_ diff --git a/core/fxcrt/xml/cxml_attritem.cpp b/core/fxcrt/xml/cxml_attritem.cpp index 8e55799a62..cbbf3f6041 100644 --- a/core/fxcrt/xml/cxml_attritem.cpp +++ b/core/fxcrt/xml/cxml_attritem.cpp @@ -6,7 +6,7 @@ #include "core/fxcrt/xml/cxml_attritem.h" -bool CXML_AttrItem::Matches(const CFX_ByteString& space, - const CFX_ByteString& name) const { +bool CXML_AttrItem::Matches(const ByteString& space, + const ByteString& name) const { return (space.IsEmpty() || m_QSpaceName == space) && m_AttrName == name; } diff --git a/core/fxcrt/xml/cxml_attritem.h b/core/fxcrt/xml/cxml_attritem.h index 63305e80c8..84d82950f9 100644 --- a/core/fxcrt/xml/cxml_attritem.h +++ b/core/fxcrt/xml/cxml_attritem.h @@ -11,11 +11,11 @@ class CXML_AttrItem { public: - bool Matches(const CFX_ByteString& space, const CFX_ByteString& name) const; + bool Matches(const ByteString& space, const ByteString& name) const; - CFX_ByteString m_QSpaceName; - CFX_ByteString m_AttrName; - CFX_WideString m_Value; + ByteString m_QSpaceName; + ByteString m_AttrName; + WideString m_Value; }; #endif // CORE_FXCRT_XML_CXML_ATTRITEM_H_ diff --git a/core/fxcrt/xml/cxml_attrmap.cpp b/core/fxcrt/xml/cxml_attrmap.cpp index 8d226fe5f0..733bbeaa71 100644 --- a/core/fxcrt/xml/cxml_attrmap.cpp +++ b/core/fxcrt/xml/cxml_attrmap.cpp @@ -13,8 +13,8 @@ CXML_AttrMap::CXML_AttrMap() {} CXML_AttrMap::~CXML_AttrMap() {} -const CFX_WideString* CXML_AttrMap::Lookup(const CFX_ByteString& space, - const CFX_ByteString& name) const { +const WideString* CXML_AttrMap::Lookup(const ByteString& space, + const ByteString& name) const { if (!m_pMap) return nullptr; @@ -25,9 +25,9 @@ const CFX_WideString* CXML_AttrMap::Lookup(const CFX_ByteString& space, return nullptr; } -void CXML_AttrMap::SetAt(const CFX_ByteString& space, - const CFX_ByteString& name, - const CFX_WideString& value) { +void CXML_AttrMap::SetAt(const ByteString& space, + const ByteString& name, + const WideString& value) { if (!m_pMap) m_pMap = pdfium::MakeUnique>(); @@ -38,7 +38,7 @@ void CXML_AttrMap::SetAt(const CFX_ByteString& space, } } - m_pMap->push_back({space, name, CFX_WideString(value)}); + m_pMap->push_back({space, name, WideString(value)}); } int CXML_AttrMap::GetSize() const { diff --git a/core/fxcrt/xml/cxml_attrmap.h b/core/fxcrt/xml/cxml_attrmap.h index 0a026d31d7..a09522b53c 100644 --- a/core/fxcrt/xml/cxml_attrmap.h +++ b/core/fxcrt/xml/cxml_attrmap.h @@ -18,14 +18,14 @@ class CXML_AttrMap { CXML_AttrMap(); ~CXML_AttrMap(); - const CFX_WideString* Lookup(const CFX_ByteString& space, - const CFX_ByteString& name) const; + const WideString* Lookup(const ByteString& space, + const ByteString& name) const; int GetSize() const; CXML_AttrItem& GetAt(int index) const; - void SetAt(const CFX_ByteString& space, - const CFX_ByteString& name, - const CFX_WideString& value); + void SetAt(const ByteString& space, + const ByteString& name, + const WideString& value); std::unique_ptr> m_pMap; }; diff --git a/core/fxcrt/xml/cxml_content.cpp b/core/fxcrt/xml/cxml_content.cpp index fe0c185bb7..a235009424 100644 --- a/core/fxcrt/xml/cxml_content.cpp +++ b/core/fxcrt/xml/cxml_content.cpp @@ -6,7 +6,7 @@ #include "core/fxcrt/xml/cxml_content.h" -CXML_Content::CXML_Content(bool bCDATA, const CFX_WideStringC& content) +CXML_Content::CXML_Content(bool bCDATA, const WideStringView& content) : m_bCDATA(bCDATA), m_Content(content) {} CXML_Content::~CXML_Content() {} diff --git a/core/fxcrt/xml/cxml_content.h b/core/fxcrt/xml/cxml_content.h index 641efe6720..97c1abfe1c 100644 --- a/core/fxcrt/xml/cxml_content.h +++ b/core/fxcrt/xml/cxml_content.h @@ -12,7 +12,7 @@ class CXML_Content : public CXML_Object { public: - CXML_Content(bool bCDATA, const CFX_WideStringC& content); + CXML_Content(bool bCDATA, const WideStringView& content); ~CXML_Content() override; // CXML_Object: @@ -20,7 +20,7 @@ class CXML_Content : public CXML_Object { const CXML_Content* AsContent() const override; bool m_bCDATA; - CFX_WideString m_Content; + WideString m_Content; }; #endif // CORE_FXCRT_XML_CXML_CONTENT_H_ diff --git a/core/fxcrt/xml/cxml_element.cpp b/core/fxcrt/xml/cxml_element.cpp index ec0a73b00d..42cbdec311 100644 --- a/core/fxcrt/xml/cxml_element.cpp +++ b/core/fxcrt/xml/cxml_element.cpp @@ -19,8 +19,8 @@ std::unique_ptr CXML_Element::Parse(const void* pBuffer, } CXML_Element::CXML_Element(const CXML_Element* pParent, - const CFX_ByteStringC& qSpace, - const CFX_ByteStringC& tagname) + const ByteStringView& qSpace, + const ByteStringView& tagname) : m_pParent(pParent), m_QSpaceName(qSpace), m_TagName(tagname) {} CXML_Element::~CXML_Element() {} @@ -33,23 +33,22 @@ const CXML_Element* CXML_Element::AsElement() const { return this; } -CFX_ByteString CXML_Element::GetTagName(bool bQualified) const { +ByteString CXML_Element::GetTagName(bool bQualified) const { if (!bQualified || m_QSpaceName.IsEmpty()) { return m_TagName; } - CFX_ByteString bsTag = m_QSpaceName; + ByteString bsTag = m_QSpaceName; bsTag += ":"; bsTag += m_TagName; return bsTag; } -CFX_ByteString CXML_Element::GetNamespace(bool bQualified) const { +ByteString CXML_Element::GetNamespace(bool bQualified) const { return bQualified ? m_QSpaceName : GetNamespaceURI(m_QSpaceName); } -CFX_ByteString CXML_Element::GetNamespaceURI( - const CFX_ByteString& qName) const { - const CFX_WideString* pwsSpace; +ByteString CXML_Element::GetNamespaceURI(const ByteString& qName) const { + const WideString* pwsSpace; const CXML_Element* pElement = this; do { if (qName.IsEmpty()) @@ -61,13 +60,13 @@ CFX_ByteString CXML_Element::GetNamespaceURI( pElement = pElement->GetParent(); } while (pElement); - return pwsSpace ? pwsSpace->UTF8Encode() : CFX_ByteString(); + return pwsSpace ? pwsSpace->UTF8Encode() : ByteString(); } void CXML_Element::GetAttrByIndex(int index, - CFX_ByteString* space, - CFX_ByteString* name, - CFX_WideString* value) const { + ByteString* space, + ByteString* name, + WideString* value) const { if (index < 0 || index >= m_AttrMap.GetSize()) return; @@ -77,26 +76,26 @@ void CXML_Element::GetAttrByIndex(int index, *value = item.m_Value; } -bool CXML_Element::HasAttr(const CFX_ByteStringC& name) const { - CFX_ByteStringC bsSpace; - CFX_ByteStringC bsName; +bool CXML_Element::HasAttr(const ByteStringView& name) const { + ByteStringView bsSpace; + ByteStringView bsName; FX_XML_SplitQualifiedName(name, bsSpace, bsName); - return !!m_AttrMap.Lookup(CFX_ByteString(bsSpace), CFX_ByteString(bsName)); + return !!m_AttrMap.Lookup(ByteString(bsSpace), ByteString(bsName)); } -bool CXML_Element::GetAttrValue(const CFX_ByteStringC& name, - CFX_WideString& attribute) const { - CFX_ByteStringC bsSpace; - CFX_ByteStringC bsName; +bool CXML_Element::GetAttrValue(const ByteStringView& name, + WideString& attribute) const { + ByteStringView bsSpace; + ByteStringView bsName; FX_XML_SplitQualifiedName(name, bsSpace, bsName); return GetAttrValue(bsSpace, bsName, attribute); } -bool CXML_Element::GetAttrValue(const CFX_ByteStringC& space, - const CFX_ByteStringC& name, - CFX_WideString& attribute) const { - const CFX_WideString* pValue = - m_AttrMap.Lookup(CFX_ByteString(space), CFX_ByteString(name)); +bool CXML_Element::GetAttrValue(const ByteStringView& space, + const ByteStringView& name, + WideString& attribute) const { + const WideString* pValue = + m_AttrMap.Lookup(ByteString(space), ByteString(name)); if (!pValue) return false; @@ -104,13 +103,13 @@ bool CXML_Element::GetAttrValue(const CFX_ByteStringC& space, return true; } -bool CXML_Element::GetAttrInteger(const CFX_ByteStringC& name, +bool CXML_Element::GetAttrInteger(const ByteStringView& name, int& attribute) const { - CFX_ByteStringC bsSpace; - CFX_ByteStringC bsName; + ByteStringView bsSpace; + ByteStringView bsName; FX_XML_SplitQualifiedName(name, bsSpace, bsName); - const CFX_WideString* pwsValue = - m_AttrMap.Lookup(CFX_ByteString(bsSpace), CFX_ByteString(bsName)); + const WideString* pwsValue = + m_AttrMap.Lookup(ByteString(bsSpace), ByteString(bsName)); if (!pwsValue) return false; @@ -118,11 +117,11 @@ bool CXML_Element::GetAttrInteger(const CFX_ByteStringC& name, return true; } -bool CXML_Element::GetAttrInteger(const CFX_ByteStringC& space, - const CFX_ByteStringC& name, +bool CXML_Element::GetAttrInteger(const ByteStringView& space, + const ByteStringView& name, int& attribute) const { - const CFX_WideString* pwsValue = - m_AttrMap.Lookup(CFX_ByteString(space), CFX_ByteString(name)); + const WideString* pwsValue = + m_AttrMap.Lookup(ByteString(space), ByteString(name)); if (!pwsValue) return false; @@ -130,19 +129,19 @@ bool CXML_Element::GetAttrInteger(const CFX_ByteStringC& space, return true; } -bool CXML_Element::GetAttrFloat(const CFX_ByteStringC& name, +bool CXML_Element::GetAttrFloat(const ByteStringView& name, float& attribute) const { - CFX_ByteStringC bsSpace; - CFX_ByteStringC bsName; + ByteStringView bsSpace; + ByteStringView bsName; FX_XML_SplitQualifiedName(name, bsSpace, bsName); return GetAttrFloat(bsSpace, bsName, attribute); } -bool CXML_Element::GetAttrFloat(const CFX_ByteStringC& space, - const CFX_ByteStringC& name, +bool CXML_Element::GetAttrFloat(const ByteStringView& space, + const ByteStringView& name, float& attribute) const { - const CFX_WideString* pValue = - m_AttrMap.Lookup(CFX_ByteString(space), CFX_ByteString(name)); + const WideString* pValue = + m_AttrMap.Lookup(ByteString(space), ByteString(name)); if (!pValue) return false; @@ -150,8 +149,8 @@ bool CXML_Element::GetAttrFloat(const CFX_ByteStringC& space, return true; } -uint32_t CXML_Element::CountElements(const CFX_ByteStringC& space, - const CFX_ByteStringC& tag) const { +uint32_t CXML_Element::CountElements(const ByteStringView& space, + const ByteStringView& tag) const { int count = 0; for (const auto& pChild : m_Children) { const CXML_Element* pKid = pChild->AsElement(); @@ -167,8 +166,8 @@ CXML_Object* CXML_Element::GetChild(uint32_t index) const { return index < m_Children.size() ? m_Children[index].get() : nullptr; } -CXML_Element* CXML_Element::GetElement(const CFX_ByteStringC& space, - const CFX_ByteStringC& tag, +CXML_Element* CXML_Element::GetElement(const ByteStringView& space, + const ByteStringView& tag, int nth) const { if (nth < 0) return nullptr; @@ -196,10 +195,10 @@ uint32_t CXML_Element::FindElement(CXML_Element* pElement) const { return 0xFFFFFFFF; } -void CXML_Element::SetTag(const CFX_ByteStringC& qTagName) { +void CXML_Element::SetTag(const ByteStringView& qTagName) { ASSERT(!qTagName.IsEmpty()); - CFX_ByteStringC bsSpace; - CFX_ByteStringC bsName; + ByteStringView bsSpace; + ByteStringView bsName; FX_XML_SplitQualifiedName(qTagName, bsSpace, bsName); m_QSpaceName = bsSpace; m_TagName = bsName; diff --git a/core/fxcrt/xml/cxml_element.h b/core/fxcrt/xml/cxml_element.h index a4b4b14129..91ac731021 100644 --- a/core/fxcrt/xml/cxml_element.h +++ b/core/fxcrt/xml/cxml_element.h @@ -18,85 +18,84 @@ class CXML_Element : public CXML_Object { static std::unique_ptr Parse(const void* pBuffer, size_t size); CXML_Element(const CXML_Element* pParent, - const CFX_ByteStringC& qSpace, - const CFX_ByteStringC& tagname); + const ByteStringView& qSpace, + const ByteStringView& tagname); ~CXML_Element() override; // CXML_Object: CXML_Element* AsElement() override; const CXML_Element* AsElement() const override; - CFX_ByteString GetTagName(bool bQualified = false) const; - CFX_ByteString GetNamespace(bool bQualified = false) const; - CFX_ByteString GetNamespaceURI(const CFX_ByteString& qName) const; + ByteString GetTagName(bool bQualified = false) const; + ByteString GetNamespace(bool bQualified = false) const; + ByteString GetNamespaceURI(const ByteString& qName) const; const CXML_Element* GetParent() const { return m_pParent.Get(); } uint32_t CountAttrs() const { return m_AttrMap.GetSize(); } void GetAttrByIndex(int index, - CFX_ByteString* space, - CFX_ByteString* name, - CFX_WideString* value) const; - bool HasAttr(const CFX_ByteStringC& qName) const; - bool GetAttrValue(const CFX_ByteStringC& name, - CFX_WideString& attribute) const; - CFX_WideString GetAttrValue(const CFX_ByteStringC& name) const { - CFX_WideString attr; + ByteString* space, + ByteString* name, + WideString* value) const; + bool HasAttr(const ByteStringView& qName) const; + bool GetAttrValue(const ByteStringView& name, WideString& attribute) const; + WideString GetAttrValue(const ByteStringView& name) const { + WideString attr; GetAttrValue(name, attr); return attr; } - bool GetAttrValue(const CFX_ByteStringC& space, - const CFX_ByteStringC& name, - CFX_WideString& attribute) const; - CFX_WideString GetAttrValue(const CFX_ByteStringC& space, - const CFX_ByteStringC& name) const { - CFX_WideString attr; + bool GetAttrValue(const ByteStringView& space, + const ByteStringView& name, + WideString& attribute) const; + WideString GetAttrValue(const ByteStringView& space, + const ByteStringView& name) const { + WideString attr; GetAttrValue(space, name, attr); return attr; } - bool GetAttrInteger(const CFX_ByteStringC& name, int& attribute) const; - int GetAttrInteger(const CFX_ByteStringC& name) const { + bool GetAttrInteger(const ByteStringView& name, int& attribute) const; + int GetAttrInteger(const ByteStringView& name) const { int attr = 0; GetAttrInteger(name, attr); return attr; } - bool GetAttrInteger(const CFX_ByteStringC& space, - const CFX_ByteStringC& name, + bool GetAttrInteger(const ByteStringView& space, + const ByteStringView& name, int& attribute) const; - int GetAttrInteger(const CFX_ByteStringC& space, - const CFX_ByteStringC& name) const { + int GetAttrInteger(const ByteStringView& space, + const ByteStringView& name) const { int attr = 0; GetAttrInteger(space, name, attr); return attr; } - bool GetAttrFloat(const CFX_ByteStringC& name, float& attribute) const; - float GetAttrFloat(const CFX_ByteStringC& name) const { + bool GetAttrFloat(const ByteStringView& name, float& attribute) const; + float GetAttrFloat(const ByteStringView& name) const { float attr = 0; GetAttrFloat(name, attr); return attr; } - bool GetAttrFloat(const CFX_ByteStringC& space, - const CFX_ByteStringC& name, + bool GetAttrFloat(const ByteStringView& space, + const ByteStringView& name, float& attribute) const; - float GetAttrFloat(const CFX_ByteStringC& space, - const CFX_ByteStringC& name) const { + float GetAttrFloat(const ByteStringView& space, + const ByteStringView& name) const { float attr = 0; GetAttrFloat(space, name, attr); return attr; } uint32_t CountChildren() const { return m_Children.size(); } - uint32_t CountElements(const CFX_ByteStringC& space, - const CFX_ByteStringC& tag) const; + uint32_t CountElements(const ByteStringView& space, + const ByteStringView& tag) const; CXML_Object* GetChild(uint32_t index) const; - CXML_Element* GetElement(const CFX_ByteStringC& space, - const CFX_ByteStringC& tag, + CXML_Element* GetElement(const ByteStringView& space, + const ByteStringView& tag, int nth) const; uint32_t FindElement(CXML_Element* pElement) const; - void SetTag(const CFX_ByteStringC& qTagName); + void SetTag(const ByteStringView& qTagName); void RemoveChild(uint32_t index); private: @@ -104,8 +103,8 @@ class CXML_Element : public CXML_Object { friend class CXML_Composer; CFX_UnownedPtr const m_pParent; - CFX_ByteString m_QSpaceName; - CFX_ByteString m_TagName; + ByteString m_QSpaceName; + ByteString m_TagName; CXML_AttrMap m_AttrMap; std::vector> m_Children; }; diff --git a/core/fxcrt/xml/cxml_parser.cpp b/core/fxcrt/xml/cxml_parser.cpp index 9679e2cd41..adf83c7148 100644 --- a/core/fxcrt/xml/cxml_parser.cpp +++ b/core/fxcrt/xml/cxml_parser.cpp @@ -78,9 +78,9 @@ bool g_FXCRT_XML_IsNameChar(uint8_t ch) { } // namespace -void FX_XML_SplitQualifiedName(const CFX_ByteStringC& bsFullName, - CFX_ByteStringC& bsSpace, - CFX_ByteStringC& bsName) { +void FX_XML_SplitQualifiedName(const ByteStringView& bsFullName, + ByteStringView& bsSpace, + ByteStringView& bsName) { if (bsFullName.IsEmpty()) return; @@ -139,7 +139,7 @@ void CXML_Parser::SkipWhiteSpaces() { } while (ReadNextBlock()); } -void CXML_Parser::GetName(CFX_ByteString* space, CFX_ByteString* name) { +void CXML_Parser::GetName(ByteString* space, ByteString* name) { m_nOffset = m_nBufferOffset + static_cast(m_dwIndex); if (IsEOF()) return; @@ -149,7 +149,7 @@ void CXML_Parser::GetName(CFX_ByteString* space, CFX_ByteString* name) { while (m_dwIndex < m_dwBufferSize) { uint8_t ch = m_pBuffer[m_dwIndex]; if (ch == ':') { - *space = CFX_ByteString(buf); + *space = ByteString(buf); buf.str(""); } else if (g_FXCRT_XML_IsNameChar(ch)) { buf << static_cast(ch); @@ -162,10 +162,10 @@ void CXML_Parser::GetName(CFX_ByteString* space, CFX_ByteString* name) { if (m_dwIndex < m_dwBufferSize || IsEOF()) break; } while (ReadNextBlock()); - *name = CFX_ByteString(buf); + *name = ByteString(buf); } -void CXML_Parser::SkipLiterals(const CFX_ByteStringC& str) { +void CXML_Parser::SkipLiterals(const ByteStringView& str) { m_nOffset = m_nBufferOffset + static_cast(m_dwIndex); if (IsEOF()) { return; @@ -281,7 +281,7 @@ uint32_t CXML_Parser::GetCharRef() { return code; } -void CXML_Parser::GetAttrValue(CFX_WideString& value) { +void CXML_Parser::GetAttrValue(WideString& value) { m_nOffset = m_nBufferOffset + static_cast(m_dwIndex); if (IsEOF()) return; @@ -323,8 +323,8 @@ void CXML_Parser::GetAttrValue(CFX_WideString& value) { void CXML_Parser::GetTagName(bool bStartTag, bool* bEndTag, - CFX_ByteString* space, - CFX_ByteString* name) { + ByteString* space, + ByteString* name) { m_nOffset = m_nBufferOffset + static_cast(m_dwIndex); if (IsEOF()) return; @@ -389,18 +389,18 @@ std::unique_ptr CXML_Parser::ParseElementInternal( if (IsEOF()) return nullptr; - CFX_ByteString tag_name; - CFX_ByteString tag_space; + ByteString tag_name; + ByteString tag_space; bool bEndTag; GetTagName(bStartTag, &bEndTag, &tag_space, &tag_name); if (tag_name.IsEmpty() || bEndTag) return nullptr; auto pElement = pdfium::MakeUnique( - pParent, tag_space.AsStringC(), tag_name.AsStringC()); + pParent, tag_space.AsStringView(), tag_name.AsStringView()); do { - CFX_ByteString attr_space; - CFX_ByteString attr_name; + ByteString attr_space; + ByteString attr_name; while (m_dwIndex < m_dwBufferSize) { SkipWhiteSpaces(); if (IsEOF()) @@ -422,7 +422,7 @@ std::unique_ptr CXML_Parser::ParseElementInternal( if (IsEOF()) break; - CFX_WideString attr_value; + WideString attr_value; GetAttrValue(attr_value); pElement->m_AttrMap.SetAt(attr_space, attr_name, attr_value); } @@ -474,19 +474,20 @@ std::unique_ptr CXML_Parser::ParseElementInternal( SkipWhiteSpaces(); iState = 0; } else if (ch == '/') { - CFX_ByteString space; - CFX_ByteString name; + ByteString space; + ByteString name; GetName(&space, &name); SkipWhiteSpaces(); m_dwIndex++; iState = 10; } else { content << decoder.GetResult(); - CFX_WideString dataStr = content.MakeString(); + WideString dataStr = content.MakeString(); if (!bCDATA) dataStr.TrimRight(L" \t\r\n"); - InsertContentSegment(bCDATA, dataStr.AsStringC(), pElement.get()); + InsertContentSegment(bCDATA, dataStr.AsStringView(), + pElement.get()); content.Clear(); decoder.Clear(); bCDATA = false; @@ -524,10 +525,10 @@ std::unique_ptr CXML_Parser::ParseElementInternal( break; } while (ReadNextBlock()); content << decoder.GetResult(); - CFX_WideString dataStr = content.MakeString(); + WideString dataStr = content.MakeString(); dataStr.TrimRight(L" \t\r\n"); - InsertContentSegment(bCDATA, dataStr.AsStringC(), pElement.get()); + InsertContentSegment(bCDATA, dataStr.AsStringView(), pElement.get()); content.Clear(); decoder.Clear(); bCDATA = false; @@ -535,7 +536,7 @@ std::unique_ptr CXML_Parser::ParseElementInternal( } void CXML_Parser::InsertContentSegment(bool bCDATA, - const CFX_WideStringC& content, + const WideStringView& content, CXML_Element* pElement) { if (content.IsEmpty()) return; diff --git a/core/fxcrt/xml/cxml_parser.h b/core/fxcrt/xml/cxml_parser.h index 33bd711ee1..ee5a1b6e18 100644 --- a/core/fxcrt/xml/cxml_parser.h +++ b/core/fxcrt/xml/cxml_parser.h @@ -26,18 +26,18 @@ class CXML_Parser { bool IsEOF(); bool HaveAvailData(); void SkipWhiteSpaces(); - void GetName(CFX_ByteString* space, CFX_ByteString* name); - void GetAttrValue(CFX_WideString& value); + void GetName(ByteString* space, ByteString* name); + void GetAttrValue(WideString& value); uint32_t GetCharRef(); void GetTagName(bool bStartTag, bool* bEndTag, - CFX_ByteString* space, - CFX_ByteString* name); - void SkipLiterals(const CFX_ByteStringC& str); + ByteString* space, + ByteString* name); + void SkipLiterals(const ByteStringView& str); std::unique_ptr ParseElement(CXML_Element* pParent, bool bStartTag); void InsertContentSegment(bool bCDATA, - const CFX_WideStringC& content, + const WideStringView& content, CXML_Element* pElement); void InsertCDATASegment(CFX_UTF8Decoder& decoder, CXML_Element* pElement); @@ -54,8 +54,8 @@ class CXML_Parser { size_t m_dwIndex; }; -void FX_XML_SplitQualifiedName(const CFX_ByteStringC& bsFullName, - CFX_ByteStringC& bsSpace, - CFX_ByteStringC& bsName); +void FX_XML_SplitQualifiedName(const ByteStringView& bsFullName, + ByteStringView& bsSpace, + ByteStringView& bsName); #endif // CORE_FXCRT_XML_CXML_PARSER_H_ -- cgit v1.2.3