11cb0ef41Sopenharmony_ci// Copyright 2019 the V8 project authors. All rights reserved. 21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be 31cb0ef41Sopenharmony_ci// found in the LICENSE file. 41cb0ef41Sopenharmony_ci 51cb0ef41Sopenharmony_ci#include 'src/builtins/builtins-string-gen.h' 61cb0ef41Sopenharmony_ci 71cb0ef41Sopenharmony_cinamespace string { 81cb0ef41Sopenharmony_ci 91cb0ef41Sopenharmony_ciextern enum TrimMode extends uint31 constexpr 'String::TrimMode' { 101cb0ef41Sopenharmony_ci kTrim, 111cb0ef41Sopenharmony_ci kTrimStart, 121cb0ef41Sopenharmony_ci kTrimEnd 131cb0ef41Sopenharmony_ci} 141cb0ef41Sopenharmony_ci 151cb0ef41Sopenharmony_ci@export 161cb0ef41Sopenharmony_cimacro IsWhiteSpaceOrLineTerminator(charCode: char16|char8): bool { 171cb0ef41Sopenharmony_ci // 0x0020 - SPACE (Intentionally out of order to fast path a commmon case) 181cb0ef41Sopenharmony_ci if (charCode == 0x0020) { 191cb0ef41Sopenharmony_ci return true; 201cb0ef41Sopenharmony_ci } 211cb0ef41Sopenharmony_ci 221cb0ef41Sopenharmony_ci // Common Non-whitespace characters from (0x000E, 0x00A0) 231cb0ef41Sopenharmony_ci if (Unsigned(Convert<int32>(charCode) - 0x000E) < 0x0092) { 241cb0ef41Sopenharmony_ci return false; 251cb0ef41Sopenharmony_ci } 261cb0ef41Sopenharmony_ci 271cb0ef41Sopenharmony_ci // 0x0009 - HORIZONTAL TAB 281cb0ef41Sopenharmony_ci if (charCode < 0x0009) { 291cb0ef41Sopenharmony_ci return false; 301cb0ef41Sopenharmony_ci } 311cb0ef41Sopenharmony_ci // 0x000A - LINE FEED OR NEW LINE 321cb0ef41Sopenharmony_ci // 0x000B - VERTICAL TAB 331cb0ef41Sopenharmony_ci // 0x000C - FORMFEED 341cb0ef41Sopenharmony_ci // 0x000D - HORIZONTAL TAB 351cb0ef41Sopenharmony_ci if (charCode <= 0x000D) { 361cb0ef41Sopenharmony_ci return true; 371cb0ef41Sopenharmony_ci } 381cb0ef41Sopenharmony_ci 391cb0ef41Sopenharmony_ci // 0x00A0 - NO-BREAK SPACE 401cb0ef41Sopenharmony_ci if (charCode == 0x00A0) { 411cb0ef41Sopenharmony_ci return true; 421cb0ef41Sopenharmony_ci } 431cb0ef41Sopenharmony_ci 441cb0ef41Sopenharmony_ci // 0x1680 - Ogham Space Mark 451cb0ef41Sopenharmony_ci if (charCode == 0x1680) { 461cb0ef41Sopenharmony_ci return true; 471cb0ef41Sopenharmony_ci } 481cb0ef41Sopenharmony_ci 491cb0ef41Sopenharmony_ci // 0x2000 - EN QUAD 501cb0ef41Sopenharmony_ci if (charCode < 0x2000) { 511cb0ef41Sopenharmony_ci return false; 521cb0ef41Sopenharmony_ci } 531cb0ef41Sopenharmony_ci // 0x2001 - EM QUAD 541cb0ef41Sopenharmony_ci // 0x2002 - EN SPACE 551cb0ef41Sopenharmony_ci // 0x2003 - EM SPACE 561cb0ef41Sopenharmony_ci // 0x2004 - THREE-PER-EM SPACE 571cb0ef41Sopenharmony_ci // 0x2005 - FOUR-PER-EM SPACE 581cb0ef41Sopenharmony_ci // 0x2006 - SIX-PER-EM SPACE 591cb0ef41Sopenharmony_ci // 0x2007 - FIGURE SPACE 601cb0ef41Sopenharmony_ci // 0x2008 - PUNCTUATION SPACE 611cb0ef41Sopenharmony_ci // 0x2009 - THIN SPACE 621cb0ef41Sopenharmony_ci // 0x200A - HAIR SPACE 631cb0ef41Sopenharmony_ci if (charCode <= 0x200A) { 641cb0ef41Sopenharmony_ci return true; 651cb0ef41Sopenharmony_ci } 661cb0ef41Sopenharmony_ci 671cb0ef41Sopenharmony_ci // 0x2028 - LINE SEPARATOR 681cb0ef41Sopenharmony_ci if (charCode == 0x2028) { 691cb0ef41Sopenharmony_ci return true; 701cb0ef41Sopenharmony_ci } 711cb0ef41Sopenharmony_ci // 0x2029 - PARAGRAPH SEPARATOR 721cb0ef41Sopenharmony_ci if (charCode == 0x2029) { 731cb0ef41Sopenharmony_ci return true; 741cb0ef41Sopenharmony_ci } 751cb0ef41Sopenharmony_ci // 0x202F - NARROW NO-BREAK SPACE 761cb0ef41Sopenharmony_ci if (charCode == 0x202F) { 771cb0ef41Sopenharmony_ci return true; 781cb0ef41Sopenharmony_ci } 791cb0ef41Sopenharmony_ci // 0x205F - MEDIUM MATHEMATICAL SPACE 801cb0ef41Sopenharmony_ci if (charCode == 0x205F) { 811cb0ef41Sopenharmony_ci return true; 821cb0ef41Sopenharmony_ci } 831cb0ef41Sopenharmony_ci // 0xFEFF - BYTE ORDER MARK 841cb0ef41Sopenharmony_ci if (charCode == 0xFEFF) { 851cb0ef41Sopenharmony_ci return true; 861cb0ef41Sopenharmony_ci } 871cb0ef41Sopenharmony_ci // 0x3000 - IDEOGRAPHIC SPACE 881cb0ef41Sopenharmony_ci if (charCode == 0x3000) { 891cb0ef41Sopenharmony_ci return true; 901cb0ef41Sopenharmony_ci } 911cb0ef41Sopenharmony_ci 921cb0ef41Sopenharmony_ci return false; 931cb0ef41Sopenharmony_ci} 941cb0ef41Sopenharmony_ci 951cb0ef41Sopenharmony_citransitioning macro StringTrimLoop<T: type>(implicit context: Context)( 961cb0ef41Sopenharmony_ci stringSlice: ConstSlice<T>, startIndex: intptr, endIndex: intptr, 971cb0ef41Sopenharmony_ci increment: intptr): intptr { 981cb0ef41Sopenharmony_ci let index = startIndex; 991cb0ef41Sopenharmony_ci while (true) { 1001cb0ef41Sopenharmony_ci if (index == endIndex) { 1011cb0ef41Sopenharmony_ci return index; 1021cb0ef41Sopenharmony_ci } 1031cb0ef41Sopenharmony_ci 1041cb0ef41Sopenharmony_ci const char: T = *stringSlice.AtIndex(index); 1051cb0ef41Sopenharmony_ci if (!IsWhiteSpaceOrLineTerminator(char)) { 1061cb0ef41Sopenharmony_ci return index; 1071cb0ef41Sopenharmony_ci } 1081cb0ef41Sopenharmony_ci index = index + increment; 1091cb0ef41Sopenharmony_ci } 1101cb0ef41Sopenharmony_ci unreachable; 1111cb0ef41Sopenharmony_ci} 1121cb0ef41Sopenharmony_ci 1131cb0ef41Sopenharmony_citransitioning macro StringTrimBody<T: type>(implicit context: Context)( 1141cb0ef41Sopenharmony_ci string: String, slice: ConstSlice<T>, variant: constexpr TrimMode): String { 1151cb0ef41Sopenharmony_ci const stringLength: intptr = string.length_intptr; 1161cb0ef41Sopenharmony_ci 1171cb0ef41Sopenharmony_ci let startIndex: intptr = 0; 1181cb0ef41Sopenharmony_ci let endIndex: intptr = stringLength - 1; 1191cb0ef41Sopenharmony_ci if (variant == TrimMode::kTrim || variant == TrimMode::kTrimStart) { 1201cb0ef41Sopenharmony_ci startIndex = StringTrimLoop(slice, startIndex, stringLength, 1); 1211cb0ef41Sopenharmony_ci if (startIndex == stringLength) { 1221cb0ef41Sopenharmony_ci return kEmptyString; 1231cb0ef41Sopenharmony_ci } 1241cb0ef41Sopenharmony_ci } 1251cb0ef41Sopenharmony_ci 1261cb0ef41Sopenharmony_ci if (variant == TrimMode::kTrim || variant == TrimMode::kTrimEnd) { 1271cb0ef41Sopenharmony_ci endIndex = StringTrimLoop(slice, endIndex, -1, -1); 1281cb0ef41Sopenharmony_ci if (endIndex == -1) { 1291cb0ef41Sopenharmony_ci return kEmptyString; 1301cb0ef41Sopenharmony_ci } 1311cb0ef41Sopenharmony_ci } 1321cb0ef41Sopenharmony_ci 1331cb0ef41Sopenharmony_ci return SubString(string, Unsigned(startIndex), Unsigned(endIndex + 1)); 1341cb0ef41Sopenharmony_ci} 1351cb0ef41Sopenharmony_ci 1361cb0ef41Sopenharmony_citransitioning macro StringTrim(implicit context: Context)( 1371cb0ef41Sopenharmony_ci receiver: JSAny, _arguments: Arguments, methodName: constexpr string, 1381cb0ef41Sopenharmony_ci variant: constexpr TrimMode): String { 1391cb0ef41Sopenharmony_ci const receiverString: String = ToThisString(receiver, methodName); 1401cb0ef41Sopenharmony_ci 1411cb0ef41Sopenharmony_ci try { 1421cb0ef41Sopenharmony_ci StringToSlice(receiverString) otherwise OneByte, TwoByte; 1431cb0ef41Sopenharmony_ci } label OneByte(slice: ConstSlice<char8>) { 1441cb0ef41Sopenharmony_ci return StringTrimBody(receiverString, slice, variant); 1451cb0ef41Sopenharmony_ci } label TwoByte(slice: ConstSlice<char16>) { 1461cb0ef41Sopenharmony_ci return StringTrimBody(receiverString, slice, variant); 1471cb0ef41Sopenharmony_ci } 1481cb0ef41Sopenharmony_ci} 1491cb0ef41Sopenharmony_ci 1501cb0ef41Sopenharmony_ci// ES6 #sec-string.prototype.trim 1511cb0ef41Sopenharmony_citransitioning javascript builtin 1521cb0ef41Sopenharmony_ciStringPrototypeTrim( 1531cb0ef41Sopenharmony_ci js-implicit context: NativeContext, receiver: JSAny)(...arguments): String { 1541cb0ef41Sopenharmony_ci const methodName: constexpr string = 'String.prototype.trim'; 1551cb0ef41Sopenharmony_ci return StringTrim(receiver, arguments, methodName, TrimMode::kTrim); 1561cb0ef41Sopenharmony_ci} 1571cb0ef41Sopenharmony_ci 1581cb0ef41Sopenharmony_ci// https://github.com/tc39/proposal-string-left-right-trim 1591cb0ef41Sopenharmony_citransitioning javascript builtin 1601cb0ef41Sopenharmony_ciStringPrototypeTrimStart( 1611cb0ef41Sopenharmony_ci js-implicit context: NativeContext, receiver: JSAny)(...arguments): String { 1621cb0ef41Sopenharmony_ci const methodName: constexpr string = 'String.prototype.trimLeft'; 1631cb0ef41Sopenharmony_ci return StringTrim(receiver, arguments, methodName, TrimMode::kTrimStart); 1641cb0ef41Sopenharmony_ci} 1651cb0ef41Sopenharmony_ci 1661cb0ef41Sopenharmony_ci// https://github.com/tc39/proposal-string-left-right-trim 1671cb0ef41Sopenharmony_citransitioning javascript builtin 1681cb0ef41Sopenharmony_ciStringPrototypeTrimEnd( 1691cb0ef41Sopenharmony_ci js-implicit context: NativeContext, receiver: JSAny)(...arguments): String { 1701cb0ef41Sopenharmony_ci const methodName: constexpr string = 'String.prototype.trimRight'; 1711cb0ef41Sopenharmony_ci return StringTrim(receiver, arguments, methodName, TrimMode::kTrimEnd); 1721cb0ef41Sopenharmony_ci} 1731cb0ef41Sopenharmony_ci} 174