RESENT - [PATCH] utf8_heavy.pl
[p5sagit/p5-mst-13.2.git] / utf8.c
diff --git a/utf8.c b/utf8.c
index 30a4908..f21b13c 100644 (file)
--- a/utf8.c
+++ b/utf8.c
@@ -68,6 +68,8 @@ Perl_uvuni_to_utf8(pTHX_ U8 *d, UV uv)
        return d;
     }
     if (uv < 0x10000) {
+        if (UNICODE_IS_SURROGATE(uv))
+           Perl_croak(aTHX_ "UTF-16 surrogate 0x%04"UVxf, uv);
        *d++ = (( uv >> 12)         | 0xe0);
        *d++ = (((uv >>  6) & 0x3f) | 0x80);
        *d++ = (( uv        & 0x3f) | 0x80);
@@ -903,7 +905,7 @@ Perl_is_uni_punct(pTHX_ UV c)
 bool
 Perl_is_uni_xdigit(pTHX_ UV c)
 {
-    U8 tmpbuf[UTF8_MAXLEN*2+1];
+    U8 tmpbuf[UTF8_MAXLEN_UCLC+1];
     uvchr_to_utf8(tmpbuf, (UV)c);
     return is_utf8_xdigit(tmpbuf);
 }
@@ -911,7 +913,7 @@ Perl_is_uni_xdigit(pTHX_ UV c)
 UV
 Perl_to_uni_upper(pTHX_ UV c, U8* p, STRLEN *lenp)
 {
-    U8 tmpbuf[UTF8_MAXLEN*2+1];
+    U8 tmpbuf[UTF8_MAXLEN_UCLC+1];
     uvchr_to_utf8(tmpbuf, (UV)c);
     return to_utf8_upper(tmpbuf, p, lenp);
 }
@@ -919,7 +921,7 @@ Perl_to_uni_upper(pTHX_ UV c, U8* p, STRLEN *lenp)
 UV
 Perl_to_uni_title(pTHX_ UV c, U8* p, STRLEN *lenp)
 {
-    U8 tmpbuf[UTF8_MAXLEN*2+1];
+    U8 tmpbuf[UTF8_MAXLEN_UCLC+1];
     uvchr_to_utf8(tmpbuf, (UV)c);
     return to_utf8_title(tmpbuf, p, lenp);
 }
@@ -927,7 +929,7 @@ Perl_to_uni_title(pTHX_ UV c, U8* p, STRLEN *lenp)
 UV
 Perl_to_uni_lower(pTHX_ UV c, U8* p, STRLEN *lenp)
 {
-    U8 tmpbuf[UTF8_MAXLEN+1];
+    U8 tmpbuf[UTF8_MAXLEN_UCLC+1];
     uvchr_to_utf8(tmpbuf, (UV)c);
     return to_utf8_lower(tmpbuf, p, lenp);
 }
@@ -935,7 +937,7 @@ Perl_to_uni_lower(pTHX_ UV c, U8* p, STRLEN *lenp)
 UV
 Perl_to_uni_fold(pTHX_ UV c, U8* p, STRLEN *lenp)
 {
-    U8 tmpbuf[UTF8_MAXLEN+1];
+    U8 tmpbuf[UTF8_MAXLEN_FOLD+1];
     uvchr_to_utf8(tmpbuf, (UV)c);
     return to_utf8_fold(tmpbuf, p, lenp);
 }
@@ -1247,7 +1249,8 @@ Perl_to_utf8_case(pTHX_ U8 *p, U8* ustrp, STRLEN *lenp, SV **swashp,char *normal
              return 0;
         }
     }
-    *lenp = UNISKIP(uv);
+    if (lenp)
+       *lenp = UNISKIP(uv);
     uvuni_to_utf8(ustrp, uv);
     return uv;
 }
@@ -1579,8 +1582,7 @@ Perl_sv_uni_display(pTHX_ SV *dsv, SV *ssv, STRLEN pvlim, UV flags)
 Return true if the strings s1 and s2 differ case-insensitively, false
 if not (if they are equal case-insensitively).  If u1 is true, the
 string s1 is assumed to be in UTF-8-encoded Unicode.  If u2 is true,
-the string s2 is assumed to be in UTF-8-encoded Unicode.  (If both u1
-and u2 are false, ibcmp() is called.)
+the string s2 is assumed to be in UTF-8-encoded Unicode.
 
 For case-insensitiveness, the "casefolding" of Unicode is used
 instead of upper/lowercasing both the characters, see
@@ -1588,50 +1590,52 @@ http://www.unicode.org/unicode/reports/tr21/ (Case Mappings).
 
 =cut */
 I32
-Perl_ibcmp_utf8(pTHX_ const char *s1, bool u1, const char *s2, bool u2, register I32 len)
-{
-     if (u1 || u2) {
-         register U8 *a = (U8*)s1;
-         register U8 *b = (U8*)s2;
-         STRLEN la, lb;
-         UV ca, cb;
-         STRLEN ulen1, ulen2;
-         U8 tmpbuf1[UTF8_MAXLEN*3+1];
-         U8 tmpbuf2[UTF8_MAXLEN*3+1];
-         
-         while (len) {
+Perl_ibcmp_utf8(pTHX_ const char *s1, bool u1, register I32 len1, const char *s2, bool u2, register I32 len2)
+{
+     register U8 *a  = (U8*)s1;
+     register U8 *b  = (U8*)s2;
+     register U8 *ae = b + len1;
+     register U8 *be = b + len2;
+     STRLEN la, lb;
+     UV ca, cb;
+     STRLEN ulen1, ulen2;
+     U8 tmpbuf1[UTF8_MAXLEN_FOLD+1];
+     U8 tmpbuf2[UTF8_MAXLEN_FOLD+1];
+     
+     while (a < ae && b < be) {
+         if (u1) {
+              if (a + UTF8SKIP(a) > ae)
+                   break;
+              ca = utf8_to_uvchr((U8*)a, &la);
+         } else {
+              ca = *a;
+              la = 1;
+         }
+         if (u2) {
+              if (b + UTF8SKIP(b) > be)
+                   break;
+              cb = utf8_to_uvchr((U8*)b, &lb);
+         } else {
+              cb = *b;
+              lb = 1;
+         }
+         if (ca != cb) {
               if (u1)
-                   ca = utf8_to_uvchr((U8*)a, &la);
-              else {
-                   ca = *a;
-                   la = 1;
-              }
+                   to_uni_fold(NATIVE_TO_UNI(ca), tmpbuf1, &ulen1);
+              else
+                   ulen1 = 1;
               if (u2)
-                   cb = utf8_to_uvchr((U8*)b, &lb);
-              else {
-                   cb = *b;
-                   lb = 1;
-              }
-              if (ca != cb) {
-                   if (u1)
-                        to_uni_fold(NATIVE_TO_UNI(ca), tmpbuf1, &ulen1);
-                   else
-                        ulen1 = 1;
-                   if (u2)
-                        to_uni_fold(NATIVE_TO_UNI(cb), tmpbuf2, &ulen2);
-                   else
-                        ulen2 = 1;
-                   if (ulen1 != ulen2
-                       || (ulen1 == 1 && PL_fold[ca] != PL_fold[cb])
-                       || memNE((char *)tmpbuf1, (char *)tmpbuf2, ulen1))
-                        return 1;
-              }
-              a += la;
-              b += lb;
+                   to_uni_fold(NATIVE_TO_UNI(cb), tmpbuf2, &ulen2);
+              else
+                   ulen2 = 1;
+              if (ulen1 != ulen2
+                  || (ulen1 == 1 && PL_fold[ca] != PL_fold[cb])
+                  || memNE((char *)tmpbuf1, (char *)tmpbuf2, ulen1))
+                   return 1; /* mismatch */
          }
-         return 0;
+         a += la;
+         b += lb;
      }
-     else
-         return ibcmp(s1, s2);
+     return a == ae && b == be ? 0 : 1; /* 0 match, 1 mismatch */
 }