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