From: Jarkko Hietaniemi Date: Tue, 1 Jan 2002 23:34:25 +0000 (+0000) Subject: Make ibcmp_utf8() more robust and make regmatch() use it. X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=d7f013c89e40f2e9536e2b2699149fb13299e6ff;p=p5sagit%2Fp5-mst-13.2.git Make ibcmp_utf8() more robust and make regmatch() use it. p4raw-id: //depot/perl@14005 --- diff --git a/regexec.c b/regexec.c index be1f2b2..4bddbf3 100644 --- a/regexec.c +++ b/regexec.c @@ -980,35 +980,30 @@ S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, char *strend, char *sta U8 tmpbuf [UTF8_MAXLEN+1]; U8 foldbuf[UTF8_MAXLEN_FOLD+1]; STRLEN len, foldlen; - - /* The ibcmp_utf8() uses to_uni_fold() which is more - * correct folding for Unicode than using lowercase. - * However, it doesn't work quite fully since the folding - * is a one-to-many mapping and the regex optimizer is - * unaware of this, so it may throw out good matches. - * Fortunately, not getting this right is allowed - * for Unicode Regular Expression Support level 1, - * only one-to-one matching is required. --jhi */ - + STRLEN mlen = utf8_length((U8*)m, (U8*)(m + ln)); + U8* l; /* The last byte of the last character in s. */ + if (c1 == c2) { while (s <= e) { c = utf8_to_uvchr((U8*)s, &len); + l = utf8_hop((U8*)s, mlen); if ( c == c1 && (ln == len || !ibcmp_utf8(s, do_utf8, - strend - s > ln ? ln : strend - s, + l - (U8*)s, m, UTF, ln)) && (norun || regtry(prog, s)) ) goto got_it; else { uvchr_to_utf8(tmpbuf, c); f = to_utf8_fold(tmpbuf, foldbuf, &foldlen); + l = utf8_hop(foldbuf, mlen); if ( f != c && (f == c1 || f == c2) && (ln == foldlen || !ibcmp_utf8((char *)foldbuf, do_utf8, - foldlen > ln ? ln : foldlen, + l - foldbuf, m, UTF, ln)) && (norun || regtry(prog, s)) ) goto got_it; @@ -1019,6 +1014,7 @@ S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, char *strend, char *sta else { while (s <= e) { c = utf8_to_uvchr((U8*)s, &len); + l = utf8_hop((U8*)s, mlen); /* Handle some of the three Greek sigmas cases. * Note that not all the possible combinations @@ -1034,19 +1030,20 @@ S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, char *strend, char *sta if ( (c == c1 || c == c2) && (ln == len || !ibcmp_utf8(s, do_utf8, - strend - s > ln ? ln : strend - s, + l - (U8*)s, m, UTF, ln)) && (norun || regtry(prog, s)) ) goto got_it; else { uvchr_to_utf8(tmpbuf, c); f = to_utf8_fold(tmpbuf, foldbuf, &foldlen); + l = utf8_hop(foldbuf, mlen); if ( f != c && (f == c1 || f == c2) && (ln == foldlen || !ibcmp_utf8((char *)foldbuf, do_utf8, - foldlen > ln ? ln : foldlen, + l - foldbuf, m, UTF, ln)) && (norun || regtry(prog, s)) ) goto got_it; @@ -2353,90 +2350,17 @@ S_regmatch(pTHX_ regnode *prog) char *l = locinput; char *e = s + ln; - if (do_utf8 != (UTF!=0)) { - /* The target and the pattern have differing utf8ness. */ - STRLEN ulen1, ulen2; - UV cs, cl; - - if (do_utf8) { - /* The target is utf8, the pattern is not utf8. */ - while (s < e) { - if (l >= PL_regeol) - sayNO; - - cs = to_uni_fold(NATIVE_TO_UNI(*(U8*)s), - (U8*)s, &ulen1); - cl = utf8_to_uvchr((U8*)l, &ulen2); - - if (cs != cl) { - cl = to_uni_fold(cl, (U8*)l, &ulen2); - if (ulen1 != ulen2 || cs != cl) - sayNO; - } - l += ulen1; - s ++; - } - } - else { - /* The target is not utf8, the pattern is utf8. */ - while (s < e) { - if (l >= PL_regeol) - sayNO; - - cs = utf8_to_uvchr((U8*)s, &ulen1); - - cl = to_uni_fold(NATIVE_TO_UNI(*(U8*)l), - (U8*)l, &ulen2); - - if (cs != cl) { - cs = to_uni_fold(cs, (U8*)s, &ulen1); - if (ulen1 != ulen2 || cs != cl) - sayNO; - } - l ++; - s += ulen1; - } - } - locinput = l; - nextchr = UCHARAT(locinput); - break; - } + if (do_utf8 || UTF) { + /* Either target or the pattern are utf8. */ + STRLEN slen = utf8_length((U8*)s, (U8*)e); + char *lend = (char *)utf8_hop((U8*)l, slen); - if (do_utf8 && UTF) { - /* Both the target and the pattern are utf8. */ - U8 lfoldbuf[UTF8_MAXLEN_FOLD+1], *lf; - U8 sfoldbuf[UTF8_MAXLEN_FOLD+1], *sf; - STRLEN lfoldlen, sfoldlen; - STRLEN llen = 0; - STRLEN slen = 0; - - while (s < e) { - /* Fold them and walk them characterwise. */ - - if (llen == 0) { - to_utf8_fold((U8*)l, lfoldbuf, &lfoldlen); - lf = lfoldbuf; - llen = lfoldlen; - } - - if (slen == 0) { - to_utf8_fold((U8*)s, sfoldbuf, &sfoldlen); - sf = sfoldbuf; - slen = sfoldlen; - } - - while (llen && slen) { - if (UTF8SKIP(lf) != UTF8SKIP(sf) || - memNE((char*)lf, (char*)sf, UTF8SKIP(lf))) - sayNO; - llen -= UTF8SKIP(lf); - lf += UTF8SKIP(lf); - slen -= UTF8SKIP(sf); - sf += UTF8SKIP(sf); - } - - l += UTF8SKIP(l); - s += UTF8SKIP(s); + if (ibcmp_utf8(s, TRUE, e - s, + l, TRUE, lend - l)) + sayNO; + else { + l = lend; + s = e; } locinput = l; nextchr = UCHARAT(locinput); diff --git a/utf8.c b/utf8.c index 500ac4b..5d42efd 100644 --- a/utf8.c +++ b/utf8.c @@ -1722,45 +1722,51 @@ http://www.unicode.org/unicode/reports/tr21/ (Case Mappings). I32 Perl_ibcmp_utf8(pTHX_ const char *s1, bool u1, register I32 len1, const char *s2, bool u2, register I32 len2) { - register U8 *p1 = (U8*)s1; - register U8 *p2 = (U8*)s2; + register U8 *p1 = (U8*)s1, *q1; + register U8 *p2 = (U8*)s2, *q2; register U8 *e1 = p1 + len1; register U8 *e2 = p2 + len2; - STRLEN l1, l2; - UV c1, c2; - STRLEN foldlen1, foldlen2; + STRLEN l1 = 0, l2 = 0; U8 foldbuf1[UTF8_MAXLEN_FOLD+1]; U8 foldbuf2[UTF8_MAXLEN_FOLD+1]; + U8 natbuf[1+1]; + STRLEN foldlen1, foldlen2; while (p1 < e1 && p2 < e2) { - if (u1) { - if (p1 + UTF8SKIP(p1) > e1) - break; - c1 = utf8_to_uvchr((U8*)p1, &l1); - } else { - c1 = NATIVE_TO_UNI(*p1); - l1 = 1; + if (l1 == 0) { + if (u1) + to_utf8_fold(p1, foldbuf1, &foldlen1); + else { + natbuf[0] = NATIVE_TO_UNI(*p1); + to_utf8_fold(natbuf, foldbuf1, &foldlen1); + } + q1 = foldbuf1; + l1 = foldlen1; } - if (u2) { - if (p2 + UTF8SKIP(p2) > e2) - break; - c2 = utf8_to_uvchr((U8*)p2, &l2); - } else { - c2 = NATIVE_TO_UNI(*p2); - l2 = 1; + if (l2 == 0) { + if (u2) + to_utf8_fold(p2, foldbuf2, &foldlen2); + else { + natbuf[0] = NATIVE_TO_UNI(*p1); + to_utf8_fold(natbuf, foldbuf2, &foldlen2); + } + q2 = foldbuf2; + l2 = foldlen2; } - if (c1 != c2) { - to_uni_fold(c1, foldbuf1, &foldlen1); - c1 = utf8_to_uvchr(foldbuf1, 0); - - to_uni_fold(c2, foldbuf2, &foldlen2); - c2 = utf8_to_uvchr(foldbuf2, 0); - - if (c1 != c2 || foldlen1 != foldlen2) - return 1; /* mismatch */ + while (l1 && l2) { + if (UTF8SKIP(q1) != UTF8SKIP(q2) || + memNE((char*)q1, (char*)q2, UTF8SKIP(q1))) + return 1; /* mismatch */ + l1 -= UTF8SKIP(q1); + q1 += UTF8SKIP(q1); + l2 -= UTF8SKIP(q2); + q2 += UTF8SKIP(q2); } - p1 += l1; - p2 += l2; + if (l1 == 0) + p1 += u1 ? UTF8SKIP(p1) : 1; + if (l2 == 0) + p2 += u2 ? UTF8SKIP(p2) : 1; + } return p1 == e1 && p2 == e2 ? 0 : 1; /* 0 match, 1 mismatch */ }