regexec.c: Add function to compare /i Latin1, pre-folded
authorKarl Williamson <khw@cpan.org>
Wed, 19 Dec 2018 18:14:58 +0000 (11:14 -0700)
committerKarl Williamson <khw@cpan.org>
Wed, 26 Dec 2018 19:50:37 +0000 (12:50 -0700)
This adds a function like Perl_foldEQ_latin1(), but the second string is
assumed to be pre-folded.  I made it a static function in the only file
that uses it, regexec.c, to take advantage of the C optimizer.

More traditionally would be to make a new API function which takes a
flags parameter.  But the whole purpose of this is speed, and so I chose
not to go that route.

embed.fnc
embed.h
proto.h
regexec.c

index 04d560b..9fdc706 100644 (file)
--- a/embed.fnc
+++ b/embed.fnc
@@ -2651,6 +2651,7 @@ EsR       |WB_enum|backup_one_WB  |NN WB_enum * previous                  \
                                |NN const U8 * const strbeg                     \
                                |NN U8 ** curpos                                \
                                |const bool utf8_target
+Ein    |I32    |foldEQ_latin1_s2_folded|NN const char* a|NN const char* b|I32 len
 #  ifdef DEBUGGING
 Es     |void   |dump_exec_pos  |NN const char *locinput|NN const regnode *scan|NN const char *loc_regeol\
                                |NN const char *loc_bostr|NN const char *loc_reg_starttry|const bool do_utf8|const U32 depth
diff --git a/embed.h b/embed.h
index ffa5b1d..7e900ed 100644 (file)
--- a/embed.h
+++ b/embed.h
 #define find_next_non_ascii    S_find_next_non_ascii
 #define find_span_end          S_find_span_end
 #define find_span_end_mask     S_find_span_end_mask
+#define foldEQ_latin1_s2_folded        S_foldEQ_latin1_s2_folded
 #define isFOO_utf8_lc(a,b,c)   S_isFOO_utf8_lc(aTHX_ a,b,c)
 #define isGCB(a,b,c,d,e)       S_isGCB(aTHX_ a,b,c,d,e)
 #define isLB(a,b,c,d,e,f)      S_isLB(aTHX_ a,b,c,d,e,f)
diff --git a/proto.h b/proto.h
index 0a373f9..41ea500 100644 (file)
--- a/proto.h
+++ b/proto.h
@@ -5834,6 +5834,11 @@ STATIC U8 *      S_find_span_end_mask(U8 * s, const U8 * send, const U8 span_byte, co
 #define PERL_ARGS_ASSERT_FIND_SPAN_END_MASK    \
        assert(s); assert(send)
 
+#ifndef PERL_NO_INLINE_FUNCTIONS
+PERL_STATIC_INLINE I32 S_foldEQ_latin1_s2_folded(const char* a, const char* b, I32 len);
+#define PERL_ARGS_ASSERT_FOLDEQ_LATIN1_S2_FOLDED       \
+       assert(a); assert(b)
+#endif
 STATIC bool    S_isFOO_utf8_lc(pTHX_ const U8 classnum, const U8* character, const U8* e)
                        __attribute__warn_unused_result__;
 #define PERL_ARGS_ASSERT_ISFOO_UTF8_LC \
index f025965..f5f6412 100644 (file)
--- a/regexec.c
+++ b/regexec.c
@@ -465,6 +465,34 @@ Perl_isFOO_lc(pTHX_ const U8 classnum, const U8 character)
 
 #endif
 
+PERL_STATIC_INLINE I32
+S_foldEQ_latin1_s2_folded(const char *s1, const char *s2, I32 len)
+{
+    /* Compare non-UTF-8 using Unicode (Latin1) semantics.  s2 must already be
+     * folded.  Works on all folds representable without UTF-8, except for
+     * LATIN_SMALL_LETTER_SHARP_S, and does not check for this.  Nor does it
+     * check that the strings each have at least 'len' characters.
+     *
+     * There is almost an identical API function where s2 need not be folded:
+     * Perl_foldEQ_latin1() */
+
+    const U8 *a = (const U8 *)s1;
+    const U8 *b = (const U8 *)s2;
+
+    PERL_ARGS_ASSERT_FOLDEQ_LATIN1_S2_FOLDED;
+
+    assert(len >= 0);
+
+    while (len--) {
+        assert(! isUPPER_L1(*b));
+        if (toLOWER_L1(*a) != *b) {
+            return 0;
+        }
+        a++, b++;
+    }
+    return 1;
+}
+
 STATIC bool
 S_isFOO_utf8_lc(pTHX_ const U8 classnum, const U8* character, const U8* e)
 {