From: Jarkko Hietaniemi Date: Thu, 13 Dec 2001 04:38:19 +0000 (+0000) Subject: It could be possible for the case-insensitive X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=332ddc25e33054764b72da8fd0b572ab1c6c6e65;p=p5sagit%2Fp5-mst-13.2.git It could be possible for the case-insensitive Unicode-aware string comparison to wander off to the la-la land. p4raw-id: //depot/perl@13669 --- diff --git a/embed.h b/embed.h index 9523ef5..ea261bf 100644 --- a/embed.h +++ b/embed.h @@ -1782,7 +1782,7 @@ #define hv_undef(a) Perl_hv_undef(aTHX_ a) #define ibcmp(a,b,c) Perl_ibcmp(aTHX_ a,b,c) #define ibcmp_locale(a,b,c) Perl_ibcmp_locale(aTHX_ a,b,c) -#define ibcmp_utf8(a,b,c,d,e) Perl_ibcmp_utf8(aTHX_ a,b,c,d,e) +#define ibcmp_utf8(a,b,c,d,e,f) Perl_ibcmp_utf8(aTHX_ a,b,c,d,e,f) #define ingroup(a,b) Perl_ingroup(aTHX_ a,b) #define init_argv_symbols(a,b) Perl_init_argv_symbols(aTHX_ a,b) #define init_debugger() Perl_init_debugger(aTHX) diff --git a/embed.pl b/embed.pl index 639ba6c..91c2ac0 100755 --- a/embed.pl +++ b/embed.pl @@ -1333,7 +1333,7 @@ Apd |HE* |hv_store_ent |HV* tb|SV* key|SV* val|U32 hash Apd |void |hv_undef |HV* tb Ap |I32 |ibcmp |const char* a|const char* b|I32 len Ap |I32 |ibcmp_locale |const char* a|const char* b|I32 len -Apd |I32 |ibcmp_utf8 |const char* a|bool ua|const char* b|bool ub|I32 len +Apd |I32 |ibcmp_utf8 |const char* a|bool ua|I32 len1|const char* b|bool ub|I32 len2 p |bool |ingroup |Gid_t testgid|Uid_t effective p |void |init_argv_symbols|int|char ** p |void |init_debugger diff --git a/pod/perlapi.pod b/pod/perlapi.pod index 6ac32f4..7bdf75c 100644 --- a/pod/perlapi.pod +++ b/pod/perlapi.pod @@ -1113,14 +1113,13 @@ Found in file hv.c 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 http://www.unicode.org/unicode/reports/tr21/ (Case Mappings). - I32 ibcmp_utf8(const char* a, bool ua, const char* b, bool ub, I32 len) + I32 ibcmp_utf8(const char* a, bool ua, I32 len1, const char* b, bool ub, I32 len2) =for hackers Found in file utf8.c diff --git a/pod/perlunicode.pod b/pod/perlunicode.pod index b1ffed5..e707dc6 100644 --- a/pod/perlunicode.pod +++ b/pod/perlunicode.pod @@ -885,9 +885,9 @@ code points). =item * -ibcmp_utf8(s1, u1, s2, u2, len) can be used to compare two strings -case-insensitively in Unicode. (For case-sensitive comparisons you -can just use memEQ() and memNE() as usual.) +ibcmp_utf8(s1, u1, len1, s2, u2, len2) can be used to compare two +strings case-insensitively in Unicode. (For case-sensitive +comparisons you can just use memEQ() and memNE() as usual.) =back diff --git a/proto.h b/proto.h index 5c9a514..f9161bb 100644 --- a/proto.h +++ b/proto.h @@ -315,7 +315,7 @@ PERL_CALLCONV HE* Perl_hv_store_ent(pTHX_ HV* tb, SV* key, SV* val, U32 hash); PERL_CALLCONV void Perl_hv_undef(pTHX_ HV* tb); PERL_CALLCONV I32 Perl_ibcmp(pTHX_ const char* a, const char* b, I32 len); PERL_CALLCONV I32 Perl_ibcmp_locale(pTHX_ const char* a, const char* b, I32 len); -PERL_CALLCONV I32 Perl_ibcmp_utf8(pTHX_ const char* a, bool ua, const char* b, bool ub, I32 len); +PERL_CALLCONV I32 Perl_ibcmp_utf8(pTHX_ const char* a, bool ua, I32 len1, const char* b, bool ub, I32 len2); PERL_CALLCONV bool Perl_ingroup(pTHX_ Gid_t testgid, Uid_t effective); PERL_CALLCONV void Perl_init_argv_symbols(pTHX_ int, char **); PERL_CALLCONV void Perl_init_debugger(pTHX); diff --git a/regexec.c b/regexec.c index 0d97be3..4b073d2 100644 --- a/regexec.c +++ b/regexec.c @@ -971,7 +971,8 @@ S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, char *strend, char *sta while (s <= e) { if ( utf8_to_uvchr((U8*)s, &len) == c1 && (ln == 1 || - ibcmp_utf8(s, do_utf8, m, UTF, ln)) ) + ibcmp_utf8(s, do_utf8, strend - s, + m, UTF, ln)) ) goto got_it; s += len; } @@ -980,7 +981,8 @@ S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, char *strend, char *sta UV c = utf8_to_uvchr((U8*)s, &len); if ( (c == c1 || c == c2) && (ln == 1 || - ibcmp_utf8(s, do_utf8, m, UTF, ln)) ) + ibcmp_utf8(s, do_utf8, strend - s, + m, UTF, ln)) ) goto got_it; s += len; } diff --git a/utf8.c b/utf8.c index 1a024b7..747b78c 100644 --- a/utf8.c +++ b/utf8.c @@ -1579,8 +1579,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 +1587,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*3+1]; + U8 tmpbuf2[UTF8_MAXLEN*3+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, len); + return a == ae && b == be ? 0 : 1; /* 0 match, 1 mismatch */ }