* Copyright (c) 2025 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "objects/string/base_string.h"
#include "objects/string/base_string-inl.h"
#include "objects/utils/utf_utils.h"
#include "common_components/base/utf_helper.h"
#include "common_components/platform/string_hash.h"
#include "common_components/platform/string_hash_helper.h"
#include <codecvt>
#include <locale>
#if !ENABLE_V70_OPTIMIZATION
#undef ENABLE_LINXKIT
#endif
#ifdef ENABLE_LINXKIT
#include "ecmascript/platform/arm64/linxkit_string.h"
#endif
namespace common {
size_t UtfUtils::DebuggerConvertRegionUtf16ToUtf8(const uint16_t* utf16In, uint8_t* utf8Out, size_t utf16Len,
size_t utf8Len, size_t start, bool modify, bool isWriteBuffer)
{
return utf_helper::DebuggerConvertRegionUtf16ToUtf8(utf16In, utf8Out, utf16Len, utf8Len, start, modify,
isWriteBuffer);
}
size_t UtfUtils::ConvertRegionUtf16ToLatin1(const uint16_t* utf16In, uint8_t* latin1Out, size_t utf16Len,
size_t latin1Len)
{
return utf_helper::ConvertRegionUtf16ToLatin1(utf16In, latin1Out, utf16Len, latin1Len);
}
template<typename T>
uint32_t ComputeHashForDataInternal(const T *data, size_t size, uint32_t hashSeed)
{
if (size <= static_cast<size_t>(StringHash::MIN_SIZE_FOR_UNROLLING)) {
uint32_t hash = hashSeed;
for (uint32_t i = 0; i < size; i++) {
hash = (hash << static_cast<uint32_t>(StringHash::HASH_SHIFT)) - hash + data[i];
}
return hash;
}
return StringHashHelper::ComputeHashForDataPlatform(data, size, hashSeed);
}
template <typename T>
uint32_t BaseString::ComputeHashForData(const T* data, size_t size,
uint32_t hashSeed)
{
#ifndef ENABLE_LINXKIT
#ifndef CMC_LCOV_EXCL
if (size <= static_cast<size_t>(StringHash::MIN_SIZE_FOR_UNROLLING)) {
uint32_t hash = hashSeed;
for (uint32_t i = 0; i < size; i++) {
hash = (hash << static_cast<uint32_t>(StringHash::HASH_SHIFT)) - hash + data[i];
}
return hash;
}
#endif
return StringHashHelper::ComputeHashForDataPlatform(data, size, hashSeed);
#else
return LinxkitComputeHashForData(data, size, hashSeed);
#endif
}
template
uint32_t BaseString::ComputeHashForData<uint8_t>(const uint8_t*, size_t, uint32_t);
template
uint32_t BaseString::ComputeHashForData<uint16_t>(const uint16_t*, size_t, uint32_t);
template <typename T1, typename T2>
uint32_t BaseString::CalculateDataConcatHashCode(const T1* dataFirst, size_t sizeFirst,
const T2* dataSecond, size_t sizeSecond)
{
uint32_t totalHash = ComputeHashForData(dataFirst, sizeFirst, 0);
totalHash = ComputeHashForData(dataSecond, sizeSecond, totalHash);
return MixHashcode(totalHash, NOT_INTEGER);
}
template
uint32_t BaseString::CalculateDataConcatHashCode<uint8_t, uint8_t>(const uint8_t* dataFirst, size_t sizeFirst,
const uint8_t* dataSecond, size_t sizeSecond);
template
uint32_t BaseString::CalculateDataConcatHashCode<uint16_t, uint16_t>(const uint16_t* dataFirst, size_t sizeFirst,
const uint16_t* dataSecond, size_t sizeSecond);
template
uint32_t BaseString::CalculateDataConcatHashCode<uint8_t, uint16_t>(const uint8_t* dataFirst, size_t sizeFirst,
const uint16_t* dataSecond, size_t sizeSecond);
template
uint32_t BaseString::CalculateDataConcatHashCode<uint16_t, uint8_t>(const uint16_t* dataFirst, size_t sizeFirst,
const uint8_t* dataSecond, size_t sizeSecond);
template <typename T1, typename T2>
bool IsSubStringAtSpan([[maybe_unused]] common::Span<T1> &lhsSp, [[maybe_unused]] common::Span<T2> &rhsSp,
[[maybe_unused]] uint32_t offset)
{
#ifndef CMC_LCOV_EXCL
size_t rhsSize = rhsSp.size();
DCHECK_CC(rhsSize + offset <= lhsSp.size());
for (size_t i = 0; i < rhsSize; ++i) {
auto left = static_cast<int32_t>(lhsSp[offset + static_cast<uint32_t>(i)]);
auto right = static_cast<int32_t>(rhsSp[i]);
if (left != right) {
return false;
}
}
#endif
return true;
}
template
bool IsSubStringAtSpan<const uint8_t, const uint8_t>(common::Span<const uint8_t>& lhsSp,
common::Span<const uint8_t>& rhsSp,
uint32_t offset);
template
bool IsSubStringAtSpan<const uint16_t, const uint16_t>(common::Span<const uint16_t>& lhsSp,
common::Span<const uint16_t>& rhsSp,
uint32_t offset);
template
bool IsSubStringAtSpan<const uint8_t, const uint16_t>(common::Span<const uint8_t>& lhsSp,
common::Span<const uint16_t>& rhsSp,
uint32_t offset);
template
bool IsSubStringAtSpan<const uint16_t, const uint8_t>(common::Span<const uint16_t>& lhsSp,
common::Span<const uint8_t>& rhsSp,
uint32_t offset);
std::u16string Utf16ToU16String(const uint16_t* utf16Data, uint32_t dataLen)
{
auto* char16tData = reinterpret_cast<const char16_t*>(utf16Data);
std::u16string u16str(char16tData, dataLen);
return u16str;
}
std::u16string Utf8ToU16String(const uint8_t* utf8Data, uint32_t dataLen)
{
auto* charData = reinterpret_cast<const char*>(utf8Data);
std::string str(charData, dataLen);
std::u16string u16str = std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t>{}.from_bytes(str);
return u16str;
}
}