regexec.c: Most /iaa nodes are now pre-folded
authorKarl Williamson <khw@cpan.org>
Sun, 23 Dec 2018 20:10:09 +0000 (13:10 -0700)
committerKarl Williamson <khw@cpan.org>
Wed, 26 Dec 2018 19:50:37 +0000 (12:50 -0700)
So, we don't have to re-fold them.

Previous commits have caused any EXACTFAA nodes to be pre-folded, and we
now have the infrastructure in regexec.c to take advantage of this,
including in non-UTF-8 patterns.  This commit changes to do this.

The only non-pre-folded EXACTFAA nodes are those that are not UTF-8, but
the target string is.  The reason is that the MICRO SIGN folds to
something representable only in UTF-8, so if you have both non-UTF-8, it
effectively is folded, and if you have the pattern in UTF-8, it gets
folded to the proper character.

In order for non-UTF-8 /iaa nodes to always be fully folded, there would
need to be a separate node for ones that contain the MICRO SIGN, and
then only that one wouldn't be considered folded when the target is
UTF-8.  I don't think it's worth it, as the only gain would be in
matching a non-UTF-8 /iaa node against a UTF-8 target string.  I suspect
/iaa will be used mostly in non-UTF8 target strings.  Comments have been
added to point this out in case someone thinks it should be implemented.

pod/perldebguts.pod
regcomp.sym
regexec.c

index f670bb2..6decb1f 100644 (file)
@@ -669,6 +669,7 @@ will be lost.
  EXACTFU_SS       str        Match this string using /iu rules (w/len);
                              (string not UTF-8, only portions guaranteed
                              to be folded; folded length > unfolded).
+
  EXACTFLU8        str        Like EXACTFU, but use /il, UTF-8, folded,
                              and everything in it is above 255.
  EXACTFAA_NO_TRIE str        Match this string using /iaa rules (w/len)
index 235305d..ab9943d 100644 (file)
@@ -108,6 +108,13 @@ EXACTFAA    EXACT,      str          ; Match this string using /iaa rules (w/len) (stri
 # End of important relative ordering.
 
 EXACTFU_SS  EXACT,      str      ; Match this string using /iu rules (w/len); (string not UTF-8, only portions guaranteed to be folded; folded length > unfolded).
+
+# In order for a non-UTF-8 EXACTFAA to think the pattern is pre-folded when
+# matching a UTF-8 target string, there would have to be something like an
+# EXACTFAA_MICRO which would not be considered pre-folded for UTF-8 targets,
+# since the fold of the MICRO SIGN would not be done, and would be
+# representable in the UTF-8 target string.
+
 EXACTFLU8   EXACT,      str      ; Like EXACTFU, but use /il, UTF-8, folded, and everything in it is above 255.
 EXACTFAA_NO_TRIE  EXACT, str     ; Match this string using /iaa rules (w/len) (string not UTF-8, not guaranteed to be folded, not currently trie-able).
 
index f5f6412..13db8fd 100644 (file)
--- a/regexec.c
+++ b/regexec.c
@@ -2277,13 +2277,28 @@ S_find_byclass(pTHX_ regexp * prog, const regnode *c, char *s,
         assert(! is_utf8_pat);
        /* FALLTHROUGH */
     case EXACTFAA:
-        if (is_utf8_pat || utf8_target) {
+        if (is_utf8_pat) {
+            utf8_fold_flags = FOLDEQ_UTF8_NOMIX_ASCII
+                             |FOLDEQ_S2_ALREADY_FOLDED|FOLDEQ_S2_FOLDS_SANE;
+            goto do_exactf_utf8;
+        }
+        else if (utf8_target) {
+
+            /* Here, and elsewhere in this file, the reason we can't consider a
+             * non-UTF-8 pattern already folded in the presence of a UTF-8
+             * target is because any MICRO SIGN in the pattern won't be folded.
+             * Since the fold of the MICRO SIGN requires UTF-8 to represent, we
+             * can consider a non-UTF-8 pattern folded when matching a
+             * non-UTF-8 target */
             utf8_fold_flags = FOLDEQ_UTF8_NOMIX_ASCII;
             goto do_exactf_utf8;
         }
-        fold_array = PL_fold_latin1;    /* Latin1 folds are not affected by */
-        folder = foldEQ_latin1;                /* /a, except the sharp s one which */
-        goto do_exactf_non_utf8;       /* isn't dealt with by these */
+
+        /* Latin1 folds are not affected by /a, except it excludes the sharp s,
+         * which these functions don't handle anyway */
+        fold_array = PL_fold_latin1;
+        folder = foldEQ_latin1_s2_folded;
+        goto do_exactf_non_utf8;
 
     case EXACTF:   /* This node only generated for non-utf8 patterns */
         assert(! is_utf8_pat);
@@ -6417,11 +6432,20 @@ S_regmatch(pTHX_ regmatch_info *reginfo, char *startpos, regnode *prog)
             assert(! is_utf8_pat);
             /* FALLTHROUGH */
        case EXACTFAA:            /*  /abc/iaa     */
-           folder = foldEQ_latin1;
+            folder = foldEQ_latin1_s2_folded;
            fold_array = PL_fold_latin1;
            fold_utf8_flags = FOLDEQ_UTF8_NOMIX_ASCII;
+            if (is_utf8_pat || ! utf8_target) {
+
+                /* The possible presence of a MICRO SIGN in the pattern forbids
+                 * us to view a non-UTF-8 pattern as folded when there is a
+                 * UTF-8 target */
+                fold_utf8_flags |= FOLDEQ_S2_ALREADY_FOLDED
+                                  |FOLDEQ_S2_FOLDS_SANE;
+            }
            goto do_exactf;
 
+
         case EXACTF:             /*  /abc/i    This node only generated for
                                                non-utf8 patterns */
             assert(! is_utf8_pat);
@@ -9296,7 +9320,14 @@ S_regrepeat(pTHX_ regexp *prog, char **startposp, const regnode *p,
         /* FALLTHROUGH */
     case EXACTFAA:
         utf8_flags = FOLDEQ_UTF8_NOMIX_ASCII;
-       goto do_exactf;
+        if (reginfo->is_utf8_pat || ! utf8_target) {
+
+            /* The possible presence of a MICRO SIGN in the pattern forbids us
+             * to view a non-UTF-8 pattern as folded when there is a UTF-8
+             * target.  */
+            utf8_flags |= FOLDEQ_S2_ALREADY_FOLDED|FOLDEQ_S2_FOLDS_SANE;
+        }
+        goto do_exactf;
 
     case EXACTFL:
         _CHECK_AND_WARN_PROBLEMATIC_LOCALE;