This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Rewrite and inline my_strnlen()
authorKarl Williamson <khw@cpan.org>
Sun, 12 Jan 2020 17:11:54 +0000 (10:11 -0700)
committerKarl Williamson <khw@cpan.org>
Tue, 14 Jan 2020 03:54:05 +0000 (20:54 -0700)
This commit changes this function to use memchr() instead of looping
byte-by-byte through the string.  And it inlines it into 3 lines of
code.  This should give comparable performance to a native libc
strnlen().

embed.fnc
inline.h
proto.h
util.c

index 1e2b7e7..296f791 100644 (file)
--- a/embed.fnc
+++ b/embed.fnc
@@ -3356,7 +3356,7 @@ ApTd      |Size_t |my_strlcpy     |NULLOK char *dst|NULLOK const char *src|Size_t siz
 #endif
 
 #ifndef HAS_STRNLEN
-ApTd   |Size_t |my_strnlen     |NN const char *str|Size_t maxlen
+AipTd  |Size_t |my_strnlen     |NN const char *str|Size_t maxlen
 #endif
 
 #ifndef HAS_MKOSTEMP
index 38b523b..7196849 100644 (file)
--- a/inline.h
+++ b/inline.h
@@ -2495,6 +2495,36 @@ Perl_foldEQ_locale(const char *s1, const char *s2, I32 len)
     return 1;
 }
 
+/*
+=for apidoc my_strnlen
+
+The C library C<strnlen> if available, or a Perl implementation of it.
+
+C<my_strnlen()> computes the length of the string, up to C<maxlen>
+characters.  It will will never attempt to address more than C<maxlen>
+characters, making it suitable for use with strings that are not
+guaranteed to be NUL-terminated.
+
+=cut
+
+Description stolen from http://man.openbsd.org/strnlen.3,
+implementation stolen from PostgreSQL.
+*/
+#ifndef HAS_STRNLEN
+
+PERL_STATIC_INLINE Size_t
+Perl_my_strnlen(const char *str, Size_t maxlen)
+{
+    const char *end = (char *) memchr(str, '\0', maxlen);
+
+    PERL_ARGS_ASSERT_MY_STRNLEN;
+
+    if (end == NULL) return maxlen;
+    return end - str;
+}
+
+#endif
+
 #if ! defined (HAS_MEMRCHR) && (defined(PERL_CORE) || defined(PERL_EXT))
 
 PERL_STATIC_INLINE void *
diff --git a/proto.h b/proto.h
index 00c42d7..a0abbdd 100644 (file)
--- a/proto.h
+++ b/proto.h
@@ -4192,10 +4192,12 @@ PERL_CALLCONV Size_t    Perl_my_strlcpy(char *dst, const char *src, Size_t size);
 #define PERL_ARGS_ASSERT_MY_STRLCPY
 #endif
 #if !defined(HAS_STRNLEN)
-PERL_CALLCONV Size_t   Perl_my_strnlen(const char *str, Size_t maxlen);
+#ifndef PERL_NO_INLINE_FUNCTIONS
+PERL_STATIC_INLINE Size_t      Perl_my_strnlen(const char *str, Size_t maxlen);
 #define PERL_ARGS_ASSERT_MY_STRNLEN    \
        assert(str)
 #endif
+#endif
 #if !defined(HAS_TRUNCATE) && !defined(HAS_CHSIZE) && defined(F_FREESP)
 PERL_CALLCONV I32      Perl_my_chsize(pTHX_ int fd, Off_t length)
                        __attribute__warn_unused_result__;
diff --git a/util.c b/util.c
index edd7dc5..8875265 100644 (file)
--- a/util.c
+++ b/util.c
@@ -5574,36 +5574,6 @@ Perl_my_strlcpy(char *dst, const char *src, Size_t size)
 }
 #endif
 
-/*
-=for apidoc my_strnlen
-
-The C library C<strnlen> if available, or a Perl implementation of it.
-
-C<my_strnlen()> computes the length of the string, up to C<maxlen>
-characters.  It will will never attempt to address more than C<maxlen>
-characters, making it suitable for use with strings that are not
-guaranteed to be NUL-terminated.
-
-=cut
-
-Description stolen from http://man.openbsd.org/strnlen.3,
-implementation stolen from PostgreSQL.
-*/
-#ifndef HAS_STRNLEN
-Size_t
-Perl_my_strnlen(const char *str, Size_t maxlen)
-{
-    const char *p = str;
-
-    PERL_ARGS_ASSERT_MY_STRNLEN;
-
-    while(maxlen-- && *p)
-        p++;
-
-    return p - str;
-}
-#endif
-
 #if defined(_MSC_VER) && (_MSC_VER >= 1300) && (_MSC_VER < 1400) && (WINVER < 0x0500)
 /* VC7 or 7.1, building with pre-VC7 runtime libraries. */
 long _ftol( double ); /* Defined by VC6 C libs. */