37bool IsReplacementCharacter(
const uint8_t* octets,
int length) {
40 if (length != 3 || octets[0] != 0xEF || octets[1] != 0xBF ||
47bool DecodeOctets(
const uint8_t* octets,
int length,
48 std::vector<base::uc16>* buffer) {
52 !IsReplacementCharacter(octets, length)) {
58 buffer->push_back(value);
67 if (character1 >
'f')
return -1;
69 if (high == -1)
return -1;
70 if (character2 >
'f')
return -1;
72 if (low == -1)
return -1;
73 return (high << 4) + low;
77void AddToBuffer(
base::uc16 decoded, String::FlatContent* uri_content,
78 int index,
bool is_uri, std::vector<T>* buffer) {
79 if (is_uri && IsReservedPredicate(decoded)) {
80 buffer->push_back(
'%');
81 base::uc16 first = uri_content->Get(index + 1);
83 DCHECK_GT(std::numeric_limits<T>::max(), first);
86 buffer->push_back(first);
89 buffer->push_back(decoded);
93bool IntoTwoByte(
int index,
bool is_uri,
int uri_length,
94 String::FlatContent* uri_content,
95 std::vector<base::uc16>* buffer) {
96 for (
int k = index; k < uri_length; k++) {
100 if (k + 2 >= uri_length ||
101 (two_digits = TwoDigitHex(uri_content->Get(k + 1),
102 uri_content->Get(k + 2))) < 0) {
111 int number_of_continuation_bytes = 0;
112 while ((decoded << ++number_of_continuation_bytes) & 0x80) {
113 if (number_of_continuation_bytes > 3 || k + 3 >= uri_length) {
116 if (uri_content->Get(++k) !=
'%' ||
117 (two_digits = TwoDigitHex(uri_content->Get(k + 1),
118 uri_content->Get(k + 2))) < 0) {
123 octets[number_of_continuation_bytes] = continuation_byte;
126 if (!DecodeOctets(octets, number_of_continuation_bytes, buffer)) {
130 AddToBuffer(decoded, uri_content, k - 2, is_uri, buffer);
133 buffer->push_back(code);
139bool IntoOneAndTwoByte(DirectHandle<String> uri,
bool is_uri,
140 std::vector<uint8_t>* one_byte_buffer,
141 std::vector<base::uc16>* two_byte_buffer) {
143 String::FlatContent uri_content = uri->GetFlatContent(no_gc);
145 int uri_length = uri->length();
146 for (
int k = 0; k < uri_length; k++) {
150 if (k + 2 >= uri_length ||
151 (two_digits = TwoDigitHex(uri_content.Get(k + 1),
152 uri_content.Get(k + 2))) < 0) {
158 return IntoTwoByte(k, is_uri, uri_length, &uri_content,
162 AddToBuffer(decoded, &uri_content, k, is_uri, one_byte_buffer);
166 return IntoTwoByte(k, is_uri, uri_length, &uri_content,
169 one_byte_buffer->push_back(code);
180 std::vector<uint8_t> one_byte_buffer;
181 std::vector<base::uc16> two_byte_buffer;
183 if (!IntoOneAndTwoByte(uri, is_uri, &one_byte_buffer, &two_byte_buffer)) {
187 if (two_byte_buffer.empty()) {
189 one_byte_buffer.data(),
static_cast<int>(one_byte_buffer.size())));
194 static_cast<int>(one_byte_buffer.size() + two_byte_buffer.size());
196 isolate,
result, isolate->factory()->NewRawTwoByteString(result_length));
200 if (!one_byte_buffer.empty()) {
201 CopyChars(chars, one_byte_buffer.data(), one_byte_buffer.size());
202 chars += one_byte_buffer.size();
204 if (!two_byte_buffer.empty()) {
205 CopyChars(chars, two_byte_buffer.data(), two_byte_buffer.size());
212bool IsUnescapePredicateInUriComponent(
base::uc16 c) {
252void AddEncodedOctetToBuffer(uint8_t octet, std::vector<uint8_t>* buffer) {
253 buffer->push_back(
'%');
258void EncodeSingle(
base::uc16 c, std::vector<uint8_t>* buffer) {
263 for (
int k = 0; k < number_of_bytes; k++) {
264 AddEncodedOctetToBuffer(s[k], buffer);
270 int number_of_bytes =
273 for (
int k = 0; k < number_of_bytes; k++) {
274 AddEncodedOctetToBuffer(s[k], buffer);
283 int uri_length = uri->length();
284 std::vector<uint8_t> buffer;
285 buffer.reserve(uri_length);
287 bool throw_error =
false;
292 for (
int k = 0; k < uri_length; k++) {
296 if (k < uri_length) {
299 EncodePair(cc1, cc2, &buffer);
304 if (IsUnescapePredicateInUriComponent(cc1) ||
305 (is_uri && IsUriSeparator(cc1))) {
306 buffer.push_back(cc1);
308 EncodeSingle(cc1, &buffer);
322 return isolate->factory()->NewStringFromOneByte(
base::VectorOf(buffer));
327template <
typename Char>
333 if (
character ==
'%' &&
i <= length - 6 && vector[
i + 1] ==
'u' &&
334 (
hi = TwoDigitHex(vector[
i + 2], vector[
i + 3])) > -1 &&
335 (
lo = TwoDigitHex(vector[
i + 4], vector[
i + 5])) > -1) {
337 return (
hi << 8) +
lo;
338 }
else if (
character ==
'%' &&
i <= length - 3 &&
339 (
lo = TwoDigitHex(vector[
i + 1], vector[
i + 2])) > -1) {
348template <
typename Char>
349MaybeHandle<String> UnescapeSlow(Isolate* isolate, DirectHandle<String>
string,
351 bool one_byte =
true;
352 uint32_t length =
string->length();
354 int unescaped_length = 0;
357 base::Vector<const Char> vector =
string->GetCharVector<Char>(no_gc);
358 for (uint32_t
i = start_index;
i <
length; unescaped_length++) {
360 if (UnescapeChar(vector,
i, length, &step) >
369 Handle<String> first_part =
370 isolate->factory()->NewProperSubString(
string, 0, start_index);
372 int dest_position = 0;
373 Handle<String> second_part;
377 ->NewRawOneByteString(unescaped_length)
380 base::Vector<const Char> vector =
string->GetCharVector<Char>(no_gc);
381 for (uint32_t
i = start_index;
i <
length; dest_position++) {
383 dest->SeqOneByteStringSet(dest_position,
384 UnescapeChar(vector,
i, length, &step));
390 ->NewRawTwoByteString(unescaped_length)
393 base::Vector<const Char> vector =
string->GetCharVector<Char>(no_gc);
394 for (uint32_t
i = start_index;
i <
length; dest_position++) {
396 dest->SeqTwoByteStringSet(dest_position,
397 UnescapeChar(vector,
i, length, &step));
402 return isolate->factory()->NewConsString(first_part, second_part);
405bool IsNotEscaped(uint16_t c) {
424template <
typename Char>
425static MaybeHandle<String> UnescapePrivate(Isolate* isolate,
426 Handle<String> source) {
431 index = search.Search(source->GetCharVector<Char>(no_gc), 0);
432 if (index < 0)
return source;
434 return UnescapeSlow<Char>(isolate, source, index);
437template <
typename Char>
438static MaybeHandle<String> EscapePrivate(Isolate* isolate,
439 Handle<String>
string) {
441 uint32_t escaped_length = 0;
442 uint32_t length =
string->length();
446 base::Vector<const Char> vector =
string->GetCharVector<Char>(no_gc);
451 }
else if (IsNotEscaped(c)) {
464 if (escaped_length == length)
return string;
468 isolate, dest, isolate->factory()->NewRawOneByteString(escaped_length));
469 int dest_position = 0;
473 base::Vector<const Char> vector =
string->GetCharVector<Char>(no_gc);
477 dest->SeqOneByteStringSet(dest_position,
'%');
478 dest->SeqOneByteStringSet(dest_position + 1,
'u');
479 dest->SeqOneByteStringSet(dest_position + 2,
481 dest->SeqOneByteStringSet(dest_position + 3,
483 dest->SeqOneByteStringSet(dest_position + 4,
485 dest->SeqOneByteStringSet(dest_position + 5,
488 }
else if (IsNotEscaped(c)) {
489 dest->SeqOneByteStringSet(dest_position, c);
492 dest->SeqOneByteStringSet(dest_position,
'%');
493 dest->SeqOneByteStringSet(dest_position + 1,
495 dest->SeqOneByteStringSet(dest_position + 2,
510 ? EscapePrivate<uint8_t>(isolate,
string)
511 : EscapePrivate<base::uc16>(isolate,
string);
518 ? UnescapePrivate<uint8_t>(isolate,
string)
519 : UnescapePrivate<base::uc16>(isolate,
string);
static uint16_t LeadSurrogate(uint32_t char_code)
static const int kNoPreviousCharacter
static const uchar kMaxNonSurrogateCharCode
static uint16_t TrailSurrogate(uint32_t char_code)
static int CombineSurrogatePair(uchar lead, uchar trail)
static bool IsTrailSurrogate(int code)
static bool IsLeadSurrogate(int code)
static uchar ValueOf(const uint8_t *str, size_t length, size_t *cursor)
static const unsigned kMaxOneByteChar
static const uchar kBadChar
static const unsigned kMaxEncodedSize
static unsigned Encode(char *out, uchar c, int previous, bool replace_invalid=false)
base::uc16 Get(uint32_t i) const
static const uint32_t kMaxLength
static V8_INLINE HandleType< String > Flatten(Isolate *isolate, HandleType< T > string, AllocationType allocation=AllocationType::kYoung)
static const int32_t kMaxOneByteCharCode
static bool IsOneByteRepresentationUnderneath(Tagged< String > string)
static MaybeDirectHandle< String > Unescape(Isolate *isolate, Handle< String > string)
static MaybeDirectHandle< String > Decode(Isolate *isolate, DirectHandle< String > uri, bool is_uri)
static MaybeDirectHandle< String > Encode(Isolate *isolate, DirectHandle< String > uri, bool is_uri)
static MaybeDirectHandle< String > Escape(Isolate *isolate, Handle< String > string)
#define ASSIGN_RETURN_ON_EXCEPTION(isolate, dst, call)
#define THROW_NEW_ERROR(isolate, call)
ZoneVector< RpoNumber > & result
InstructionOperand source
char HexCharOfValue(int value)
Vector< const uint8_t > StaticOneByteVector(const char(&array)[N])
constexpr Vector< T > VectorOf(T *start, size_t size)
PerThreadAssertScopeDebugOnly< false, SAFEPOINTS_ASSERT, HEAP_ALLOCATION_ASSERT > DisallowGarbageCollection
BUILTIN_FP_CALL BUILTIN_FP_CALL BUILTIN_FP_CALL BUILTIN_FP_CALL BUILTIN_FP_CALL BUILTIN_FP_CALL BUILTIN_FP_CALL BUILTIN_FP_CALL BUILTIN_FP_CALL BUILTIN_FP_CALL int character
void CopyChars(DstType *dst, const SrcType *src, size_t count) V8_NONNULL(1
constexpr bool IsAlphaNumeric(base::uc32 c)
template const char * string
#define DCHECK_LE(v1, v2)
#define DCHECK(condition)
#define DCHECK_LT(v1, v2)
#define DCHECK_GT(v1, v2)