UTF-8 tr/// battle continues, ammunition from Inaba Hiroto.
Jarkko Hietaniemi [Mon, 19 Mar 2001 18:58:43 +0000 (18:58 +0000)]
TODO: tests.

p4raw-id: //depot/perl@9242

doop.c
op.c

diff --git a/doop.c b/doop.c
index e4a516a..b3c4acb 100644 (file)
--- a/doop.c
+++ b/doop.c
@@ -402,6 +402,7 @@ S_do_trans_count_utf8(pTHX_ SV *sv)/* SPC - OK */
     HV* hv = (HV*)SvRV(rv);
     SV** svp = hv_fetch(hv, "NONE", 4, FALSE);
     UV none = svp ? SvUV(*svp) : 0x7fffffff;
+    UV extra = none + 1;
     UV uv;
     U8 hibit = 0;
 
@@ -417,7 +418,7 @@ S_do_trans_count_utf8(pTHX_ SV *sv)/* SPC - OK */
     send = s + len;
 
     while (s < send) {
-       if ((uv = swash_fetch(rv, s)) < none)
+       if ((uv = swash_fetch(rv, s)) < none || uv == extra)
            matches++;
        s += UTF8SKIP(s);
     }
@@ -443,6 +444,7 @@ S_do_trans_complex_utf8(pTHX_ SV *sv) /* SPC - NOT OK */
     UV none = svp ? SvUV(*svp) : 0x7fffffff;
     UV extra = none + 1;
     UV final;
+    bool havefinal = FALSE;
     UV uv;
     STRLEN len;
     U8 *dstart, *dend;
@@ -463,8 +465,10 @@ S_do_trans_complex_utf8(pTHX_ SV *sv) /* SPC - NOT OK */
     start = s;
 
     svp = hv_fetch(hv, "FINAL", 5, FALSE);
-    if (svp)
+    if (svp) {
        final = SvUV(*svp);
+       havefinal = TRUE;
+    }
 
     if (grows) {
        /* d needs to be bigger than s, in case e.g. upgrading is required */
@@ -510,10 +514,22 @@ S_do_trans_complex_utf8(pTHX_ SV *sv) /* SPC - NOT OK */
            }
            else if (uv == extra && !del) {
                matches++;
-               s += UTF8SKIP(s);
-               if (uv != puv) {
-                   d = uvchr_to_utf8(d, final);
-                   puv = final;
+               if (havefinal) {
+                   s += UTF8SKIP(s);
+                   if (puv != final) {
+                       d = uvchr_to_utf8(d, final);
+                       puv = final;
+                   }
+               }
+               else {
+                   STRLEN len;
+                   uv = utf8_to_uvchr(s, &len);
+                   if (uv != puv) {
+                       Copy(s, d, len, U8);
+                       d += len;
+                       puv = uv;
+                   }
+                   s += len;
                }
                continue;
            }
diff --git a/op.c b/op.c
index 25e7aa5..5cdb3df 100644 (file)
--- a/op.c
+++ b/op.c
@@ -2710,7 +2710,7 @@ Perl_pmtrans(pTHX_ OP *o, OP *expr, OP *repl)
        I32 from_utf    = o->op_private & OPpTRANS_FROM_UTF;
        I32 to_utf      = o->op_private & OPpTRANS_TO_UTF;
        U8* tsave = from_utf ? NULL : trlist_upgrade(&t, &tend);
-       U8* rsave = to_utf   ? NULL : trlist_upgrade(&r, &rend);
+       U8* rsave = (to_utf || !rlen) ? NULL : trlist_upgrade(&r, &rend);
 
        if (complement) {
            U8 tmpbuf[UTF8_MAXLEN+1];
@@ -2832,9 +2832,10 @@ Perl_pmtrans(pTHX_ OP *o, OP *expr, OP *repl)
 
                if (rfirst + diff > max)
                    max = rfirst + diff;
-               rfirst += diff + 1;
                if (!grows)
-                   grows = (UNISKIP(tfirst) < UNISKIP(rfirst));
+                   grows = (tfirst < rfirst &&
+                            UNISKIP(tfirst) < UNISKIP(rfirst + diff));
+               rfirst += diff + 1;
            }
            tfirst += diff + 1;
        }
@@ -2856,7 +2857,7 @@ Perl_pmtrans(pTHX_ OP *o, OP *expr, OP *repl)
        if (transv)
            SvREFCNT_dec(transv);
 
-       if (!del && havefinal)
+       if (!del && havefinal && rlen)
            (void)hv_store((HV*)SvRV((cSVOPo->op_sv)), "FINAL", 5,
                           newSVuv((UV)final), 0);