Here's a patch to implement the split opcode such that it splits on strings rather than regular expressions. I've also added a test to t/op/string.t
Files affected: M ops/string.ops M t/op/string.t -Scott -- Jonathan Scott Duff [EMAIL PROTECTED]
=== ops/string.ops ================================================================== --- ops/string.ops (revision 63) +++ ops/string.ops (local) @@ -479,8 +479,10 @@ =item B<split>(out PMC, in STR, in STR) -Create a new Array PMC $1 by splitting the string $3 with -regexp $2. Currently implemented only for the empty string $2. +Create a new Array PMC $1 by splitting the string $3 into pieces +delimited by the string $2. If $2 does not appear in $3, then return $3 +as the sole element of the Array PMC. Will return empty strings for +delimiters at the beginning and end of $3 =cut @@ -507,22 +509,43 @@ } op split(out PMC, in STR, in STR) :base_core { - PMC *res = $1 = pmc_new(interpreter, enum_class_Array); - STRING *r = $2; - STRING *s = $3; - int slen = string_length(interpreter, s); - int i; + PMC *res = $1 = pmc_new(interpreter, enum_class_ResizableStringArray); + STRING *delim = $2; + STRING *str = $3; + int dlen = string_length(interpreter, delim); + int slen = string_length(interpreter, str); + int ps,pe; if (!slen) goto NEXT(); - if (string_length(interpreter, r)) - internal_exception(1, "Unimplemented split by regex"); - VTABLE_set_integer_native(interpreter, res, slen); - for (i = 0; i < slen; ++i) { - STRING *p = string_substr(interpreter, s, i, 1, NULL, 0); - /* TODO first set empty string, then replace */ - VTABLE_set_string_keyed_int(interpreter, res, i, p); + + if (dlen == 0) { + int i; + VTABLE_set_integer_native(interpreter, res, slen); + for (i = 0; i < slen; ++i) { + STRING *p = string_substr(interpreter, str, i, 1, NULL, 0); + VTABLE_set_string_keyed_int(interpreter, res, i, p); + } + goto NEXT(); } + + ps = 0; + pe = string_str_index(interpreter,str,delim,0); + if (pe < 0) { + VTABLE_push_string(interpreter,res,str); + goto NEXT(); + } + while (ps <= slen) { + int pl = pe - ps; + STRING *tstr = string_substr(interpreter, str, ps, pl, NULL, 0); + VTABLE_push_string(interpreter,res,tstr); + ps = pe + string_length(interpreter,delim); + if (ps > slen) + break; + pe = string_str_index(interpreter,str,delim,ps); + if (pe < 0) + pe = slen; + } goto NEXT(); } === t/op/string.t ================================================================== --- t/op/string.t (revision 63) +++ t/op/string.t (local) @@ -16,7 +16,7 @@ =cut -use Parrot::Test tests => 156; +use Parrot::Test tests => 157; use Test::More; output_is( <<'CODE', <<OUTPUT, "set_s_s|sc" ); @@ -2555,7 +2555,7 @@ return $rt; } -output_is( <<'CODE', <<OUTPUT, "split"); +output_is( <<'CODE', <<'OUTPUT', "split on empty string"); _main: split P1, "", "" set I1, P1 @@ -2577,8 +2577,32 @@ ab OUTPUT -output_is( <<'CODE', <<OUTPUT, "join"); +output_is( <<'CODE', <<'OUTPUT', "split on non-empty string"); _main: + split P0, "a", "afooabara" + set I0, P0 + print I0 + print "\n" + set I1, 0 +loop: + set S0, P0[I1] + print S0 + print "\n" + inc I1 + sub I2, I1, I0 + if I2, loop + end +CODE +5 + +foo +b +r + +OUTPUT + +output_is( <<'CODE', <<'OUTPUT', "join"); +_main: new P0, .PerlArray join S0, "--", P0 print S0