michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: michael@0: /** michael@0: * File Name: String/split-002.js michael@0: * ECMA Section: 15.6.4.9 michael@0: * Description: Based on ECMA 2 Draft 7 February 1999 michael@0: * michael@0: * Author: christine@netscape.com michael@0: * Date: 19 February 1999 michael@0: */ michael@0: michael@0: /* michael@0: * Since regular expressions have been part of JavaScript since 1.2, there michael@0: * are already tests for regular expressions in the js1_2/regexp folder. michael@0: * michael@0: * These new tests try to supplement the existing tests, and verify that michael@0: * our implementation of RegExp conforms to the ECMA specification, but michael@0: * does not try to be as exhaustive as in previous tests. michael@0: * michael@0: * The [,limit] argument to String.split is new, and not covered in any michael@0: * existing tests. michael@0: * michael@0: * String.split cases are covered in ecma/String/15.5.4.8-*.js. michael@0: * String.split where separator is a RegExp are in michael@0: * js1_2/regexp/string_split.js michael@0: * michael@0: */ michael@0: michael@0: var SECTION = "ecma_2/String/split-002.js"; michael@0: var VERSION = "ECMA_2"; michael@0: var TITLE = "String.prototype.split( regexp, [,limit] )"; michael@0: michael@0: startTest(); michael@0: michael@0: // the separator is not supplied michael@0: // separator is undefined michael@0: // separator is an empty string michael@0: michael@0: // AddSplitCases( "splitme", "", "''", ["s", "p", "l", "i", "t", "m", "e"] ); michael@0: // AddSplitCases( "splitme", new RegExp(), "new RegExp()", ["s", "p", "l", "i", "t", "m", "e"] ); michael@0: michael@0: // separator is an empty regexp michael@0: // separator is not supplied michael@0: michael@0: CompareSplit( "hello", "ll" ); michael@0: michael@0: CompareSplit( "hello", "l" ); michael@0: CompareSplit( "hello", "x" ); michael@0: CompareSplit( "hello", "h" ); michael@0: CompareSplit( "hello", "o" ); michael@0: CompareSplit( "hello", "hello" ); michael@0: CompareSplit( "hello", undefined ); michael@0: michael@0: CompareSplit( "hello", ""); michael@0: CompareSplit( "hello", "hellothere" ); michael@0: michael@0: CompareSplit( new String("hello" ) ); michael@0: michael@0: michael@0: Number.prototype.split = String.prototype.split; michael@0: michael@0: CompareSplit( new Number(100111122133144155), 1 ); michael@0: CompareSplitWithLimit(new Number(100111122133144155), 1, 1 ); michael@0: michael@0: CompareSplitWithLimit(new Number(100111122133144155), 1, 2 ); michael@0: CompareSplitWithLimit(new Number(100111122133144155), 1, 0 ); michael@0: CompareSplitWithLimit(new Number(100111122133144155), 1, 100 ); michael@0: CompareSplitWithLimit(new Number(100111122133144155), 1, void 0 ); michael@0: CompareSplitWithLimit(new Number(100111122133144155), 1, Math.pow(2,32)-1 ); michael@0: CompareSplitWithLimit(new Number(100111122133144155), 1, "boo" ); michael@0: CompareSplitWithLimit(new Number(100111122133144155), 1, -(Math.pow(2,32)-1) ); michael@0: CompareSplitWithLimit( "hello", "l", NaN ); michael@0: CompareSplitWithLimit( "hello", "l", 0 ); michael@0: CompareSplitWithLimit( "hello", "l", 1 ); michael@0: CompareSplitWithLimit( "hello", "l", 2 ); michael@0: CompareSplitWithLimit( "hello", "l", 3 ); michael@0: CompareSplitWithLimit( "hello", "l", 4 ); michael@0: michael@0: michael@0: /* michael@0: CompareSplitWithLimit( "hello", "ll", 0 ); michael@0: CompareSplitWithLimit( "hello", "ll", 1 ); michael@0: CompareSplitWithLimit( "hello", "ll", 2 ); michael@0: CompareSplit( "", " " ); michael@0: CompareSplit( "" ); michael@0: */ michael@0: michael@0: // separartor is a regexp michael@0: // separator regexp value global setting is set michael@0: // string is an empty string michael@0: // if separator is an empty string, split each by character michael@0: michael@0: // this is not a String object michael@0: michael@0: // limit is not a number michael@0: // limit is undefined michael@0: // limit is larger than 2^32-1 michael@0: // limit is a negative number michael@0: michael@0: test(); michael@0: michael@0: function CompareSplit( string, separator ) { michael@0: split_1 = string.split( separator ); michael@0: split_2 = string_split( string, separator ); michael@0: michael@0: AddTestCase( michael@0: "( " + string +".split(" + separator + ") ).length" , michael@0: split_2.length, michael@0: split_1.length ); michael@0: michael@0: var limit = split_1.length > split_2.length ? michael@0: split_1.length : split_2.length; michael@0: michael@0: for ( var split_item = 0; split_item < limit; split_item++ ) { michael@0: AddTestCase( michael@0: string + ".split(" + separator + ")["+split_item+"]", michael@0: split_2[split_item], michael@0: split_1[split_item] ); michael@0: } michael@0: } michael@0: michael@0: function CompareSplitWithLimit( string, separator, splitlimit ) { michael@0: split_1 = string.split( separator, splitlimit ); michael@0: split_2 = string_split( string, separator, splitlimit ); michael@0: michael@0: AddTestCase( michael@0: "( " + string +".split(" + separator + ", " + splitlimit+") ).length" , michael@0: split_2.length, michael@0: split_1.length ); michael@0: michael@0: var limit = split_1.length > split_2.length ? michael@0: split_1.length : split_2.length; michael@0: michael@0: for ( var split_item = 0; split_item < limit; split_item++ ) { michael@0: AddTestCase( michael@0: string + ".split(" + separator + ", " + splitlimit+")["+split_item+"]", michael@0: split_2[split_item], michael@0: split_1[split_item] ); michael@0: } michael@0: } michael@0: michael@0: function string_split ( __this, separator, limit ) { michael@0: var S = String(__this ); // 1 michael@0: michael@0: var A = new Array(); // 2 michael@0: michael@0: if ( limit == undefined ) { // 3 michael@0: lim = Math.pow(2, 31 ) -1; michael@0: } else { michael@0: lim = ToUint32( limit ); michael@0: } michael@0: michael@0: var s = S.length; // 4 michael@0: var p = 0; // 5 michael@0: michael@0: if ( separator == undefined ) { // 8 michael@0: A[0] = S; michael@0: return A; michael@0: } michael@0: michael@0: if ( separator.constructor == RegExp ) // 6 michael@0: R = separator; michael@0: else michael@0: R = separator.toString(); michael@0: michael@0: if (lim == 0) return A; // 7 michael@0: michael@0: if ( separator == undefined ) { // 8 michael@0: A[0] = S; michael@0: return A; michael@0: } michael@0: michael@0: if (s == 0) { // 9 michael@0: z = SplitMatch(R, S, 0); michael@0: if (z != false) return A; michael@0: A[0] = S; michael@0: return A; michael@0: } michael@0: michael@0: var q = p; // 10 michael@0: loop: michael@0: while (true ) { michael@0: michael@0: if ( q == s ) break; // 11 michael@0: michael@0: z = SplitMatch(R, S, q); // 12 michael@0: michael@0: //print("Returned ", z); michael@0: michael@0: if (z != false) { // 13 michael@0: e = z.endIndex; // 14 michael@0: cap = z.captures; // 14 michael@0: if (e != p) { // 15 michael@0: //print("S = ", S, ", p = ", p, ", q = ", q); michael@0: T = S.slice(p, q); // 16 michael@0: //print("T = ", T); michael@0: A[A.length] = T; // 17 michael@0: if (A.length == lim) return A; // 18 michael@0: p = e; // 19 michael@0: i = 0; // 20 michael@0: while (true) { // 25 michael@0: if (i == cap.length) { // 21 michael@0: q = p; // 10 michael@0: continue loop; michael@0: } michael@0: i = i + 1; // 22 michael@0: A[A.length] = cap[i] // 23 michael@0: if (A.length == lim) return A; // 24 michael@0: } michael@0: } michael@0: } michael@0: michael@0: q = q + 1; // 26 michael@0: } michael@0: michael@0: T = S.slice(p, q); michael@0: A[A.length] = T; michael@0: return A; michael@0: } michael@0: michael@0: function SplitMatch(R, S, q) michael@0: { michael@0: if (R.constructor == RegExp) { // 1 michael@0: var reResult = R.match(S, q); // 8 michael@0: if (reResult == undefined) michael@0: return false; michael@0: else { michael@0: a = new Array(reResult.length - 1); michael@0: for (var i = 1; i < reResult.length; i++) michael@0: a[a.length] = reResult[i]; michael@0: return { endIndex : reResult.index + reResult[0].length, captures : cap }; michael@0: } michael@0: } michael@0: else { michael@0: var r = R.length; // 2 michael@0: s = S.length; // 3 michael@0: if ((q + r) > s) return false; // 4 michael@0: for (var i = 0; i < r; i++) { michael@0: //print("S.charAt(", q + i, ") = ", S.charAt(q + i), ", R.charAt(", i, ") = ", R.charAt(i)); michael@0: if (S.charAt(q + i) != R.charAt(i)) // 5 michael@0: return false; michael@0: } michael@0: cap = new Array(); // 6 michael@0: return { endIndex : q + r, captures : cap }; // 7 michael@0: } michael@0: } michael@0: michael@0: function ToUint32( n ) { michael@0: n = Number( n ); michael@0: var sign = ( n < 0 ) ? -1 : 1; michael@0: michael@0: if ( Math.abs( n ) == 0 michael@0: || Math.abs( n ) == Number.POSITIVE_INFINITY michael@0: || n != n) { michael@0: return 0; michael@0: } michael@0: n = sign * Math.floor( Math.abs(n) ) michael@0: michael@0: n = n % Math.pow(2,32); michael@0: michael@0: if ( n < 0 ){ michael@0: n += Math.pow(2,32); michael@0: } michael@0: michael@0: return ( n ); michael@0: }