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

Reply via email to