blob: daaec9973889f0880f47b19d6fa38240bb110d36 [file] [log] [blame]
// Copyright 2019 the V8 project 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 'src/builtins/builtins-string-gen.h'
namespace string {
extern enum TrimMode extends uint31 constexpr 'String::TrimMode' {
kTrim,
kTrimStart,
kTrimEnd
}
@export
macro IsWhiteSpaceOrLineTerminator(charCode: char16|char8): bool {
// 0x0020 - SPACE (Intentionally out of order to fast path a commmon case)
if (charCode == 0x0020) {
return true;
}
// Common Non-whitespace characters from (0x000E, 0x00A0)
if (Unsigned(Convert<int32>(charCode) - 0x000E) < 0x0092) {
return false;
}
// 0x0009 - HORIZONTAL TAB
if (charCode < 0x0009) {
return false;
}
// 0x000A - LINE FEED OR NEW LINE
// 0x000B - VERTICAL TAB
// 0x000C - FORMFEED
// 0x000D - HORIZONTAL TAB
if (charCode <= 0x000D) {
return true;
}
// 0x00A0 - NO-BREAK SPACE
if (charCode == 0x00A0) {
return true;
}
// 0x1680 - Ogham Space Mark
if (charCode == 0x1680) {
return true;
}
// 0x2000 - EN QUAD
if (charCode < 0x2000) {
return false;
}
// 0x2001 - EM QUAD
// 0x2002 - EN SPACE
// 0x2003 - EM SPACE
// 0x2004 - THREE-PER-EM SPACE
// 0x2005 - FOUR-PER-EM SPACE
// 0x2006 - SIX-PER-EM SPACE
// 0x2007 - FIGURE SPACE
// 0x2008 - PUNCTUATION SPACE
// 0x2009 - THIN SPACE
// 0x200A - HAIR SPACE
if (charCode <= 0x200A) {
return true;
}
// 0x2028 - LINE SEPARATOR
if (charCode == 0x2028) {
return true;
}
// 0x2029 - PARAGRAPH SEPARATOR
if (charCode == 0x2029) {
return true;
}
// 0x202F - NARROW NO-BREAK SPACE
if (charCode == 0x202F) {
return true;
}
// 0x205F - MEDIUM MATHEMATICAL SPACE
if (charCode == 0x205F) {
return true;
}
// 0xFEFF - BYTE ORDER MARK
if (charCode == 0xFEFF) {
return true;
}
// 0x3000 - IDEOGRAPHIC SPACE
if (charCode == 0x3000) {
return true;
}
return false;
}
transitioning macro StringTrimLoop<T: type>(implicit context: Context)(
stringSlice: ConstSlice<T>, startIndex: intptr, endIndex: intptr,
increment: intptr): intptr {
let index = startIndex;
while (true) {
if (index == endIndex) {
return index;
}
const char: T = *stringSlice.AtIndex(index);
if (!IsWhiteSpaceOrLineTerminator(char)) {
return index;
}
index = index + increment;
}
unreachable;
}
transitioning macro StringTrimBody<T: type>(implicit context: Context)(
string: String, slice: ConstSlice<T>, variant: constexpr TrimMode): String {
const stringLength: intptr = string.length_intptr;
let startIndex: intptr = 0;
let endIndex: intptr = stringLength - 1;
if (variant == TrimMode::kTrim || variant == TrimMode::kTrimStart) {
startIndex = StringTrimLoop(slice, startIndex, stringLength, 1);
if (startIndex == stringLength) {
return kEmptyString;
}
}
if (variant == TrimMode::kTrim || variant == TrimMode::kTrimEnd) {
endIndex = StringTrimLoop(slice, endIndex, -1, -1);
if (endIndex == -1) {
return kEmptyString;
}
}
return SubString(string, Unsigned(startIndex), Unsigned(endIndex + 1));
}
transitioning macro StringTrim(implicit context: Context)(
receiver: JSAny, _arguments: Arguments, methodName: constexpr string,
variant: constexpr TrimMode): String {
const receiverString: String = ToThisString(receiver, methodName);
try {
StringToSlice(receiverString) otherwise OneByte, TwoByte;
} label OneByte(slice: ConstSlice<char8>) {
return StringTrimBody(receiverString, slice, variant);
} label TwoByte(slice: ConstSlice<char16>) {
return StringTrimBody(receiverString, slice, variant);
}
}
// ES6 #sec-string.prototype.trim
transitioning javascript builtin
StringPrototypeTrim(
js-implicit context: NativeContext, receiver: JSAny)(...arguments): String {
const methodName: constexpr string = 'String.prototype.trim';
return StringTrim(receiver, arguments, methodName, TrimMode::kTrim);
}
// https://github.com/tc39/proposal-string-left-right-trim
transitioning javascript builtin
StringPrototypeTrimStart(
js-implicit context: NativeContext, receiver: JSAny)(...arguments): String {
const methodName: constexpr string = 'String.prototype.trimLeft';
return StringTrim(receiver, arguments, methodName, TrimMode::kTrimStart);
}
// https://github.com/tc39/proposal-string-left-right-trim
transitioning javascript builtin
StringPrototypeTrimEnd(
js-implicit context: NativeContext, receiver: JSAny)(...arguments): String {
const methodName: constexpr string = 'String.prototype.trimRight';
return StringTrim(receiver, arguments, methodName, TrimMode::kTrimEnd);
}
}