]> Savannah Git Hosting - gnulib.git/commitdiff
unistr/u{16,32}-strstr: Use two-way algorithm (no memory allocation).
authorBruno Haible <bruno@clisp.org>
Sun, 2 Apr 2023 14:07:36 +0000 (16:07 +0200)
committerBruno Haible <bruno@clisp.org>
Sun, 2 Apr 2023 14:07:36 +0000 (16:07 +0200)
* lib/wcs-two-way.h: Use UNIT instead of wchar_t. Don't undefine
RETURN_TYPE.
* lib/wcsstr-impl.h: Move the non-linear implementation away. Use UNIT
instead of wchar_t, RETURN_TYPE instead of 'wchar_t *', FUNC instead of
wcsstr.
(AVAILABLE): Use MEMCHR0 instead of wmemchr.
(FUNC): Use STRCHR instead of wcschr.
* lib/wcsstr.c: Moved the non-linear implementation to here.
(FUNC, UNIT, RETURN_TYPE, MEMCHR0, STRCHR): New macros.
* lib/unistr/u16-strstr.c: Don't include malloca.h, str-kmp.h,
u-strstr.h. Instead, include wcsstr-impl.h.
* lib/unistr/u32-strstr.c: Likewise.
* modules/unistr/u16-strstr (Files): Remove u-strstr.h, str-kmp.h. Add
wcsstr-impl.h, wcs-two-way.h.
(Depends-on): Remove u16-strmbtouc, u16-strlen, u16-strnlen, malloca.
Add u16-chr, u16-cmp.
* modules/unistr/u32-strstr (Files): Remove u-strstr.h, str-kmp.h. Add
wcsstr-impl.h, wcs-two-way.h.
(Depends-on): Remove u32-strlen, u32-strnlen, malloca. Add u32-chr,
u32-cmp.

ChangeLog
lib/unistr/u16-strstr.c
lib/unistr/u32-strstr.c
lib/wcs-two-way.h
lib/wcsstr-impl.h
lib/wcsstr.c
modules/unistr/u16-strstr
modules/unistr/u32-strstr

index ddc568db032c77e9e515c44faf0dbe2bd88c5a17..f933d1e94db3fd4c32df5d8dbbd74a8873acda53 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,27 @@
+2023-04-02  Bruno Haible  <bruno@clisp.org>
+
+       unistr/u{16,32}-strstr: Use two-way algorithm (no memory allocation).
+       * lib/wcs-two-way.h: Use UNIT instead of wchar_t. Don't undefine
+       RETURN_TYPE.
+       * lib/wcsstr-impl.h: Move the non-linear implementation away. Use UNIT
+       instead of wchar_t, RETURN_TYPE instead of 'wchar_t *', FUNC instead of
+       wcsstr.
+       (AVAILABLE): Use MEMCHR0 instead of wmemchr.
+       (FUNC): Use STRCHR instead of wcschr.
+       * lib/wcsstr.c: Moved the non-linear implementation to here.
+       (FUNC, UNIT, RETURN_TYPE, MEMCHR0, STRCHR): New macros.
+       * lib/unistr/u16-strstr.c: Don't include malloca.h, str-kmp.h,
+       u-strstr.h. Instead, include wcsstr-impl.h.
+       * lib/unistr/u32-strstr.c: Likewise.
+       * modules/unistr/u16-strstr (Files): Remove u-strstr.h, str-kmp.h. Add
+       wcsstr-impl.h, wcs-two-way.h.
+       (Depends-on): Remove u16-strmbtouc, u16-strlen, u16-strnlen, malloca.
+       Add u16-chr, u16-cmp.
+       * modules/unistr/u32-strstr (Files): Remove u-strstr.h, str-kmp.h. Add
+       wcsstr-impl.h, wcs-two-way.h.
+       (Depends-on): Remove u32-strlen, u32-strnlen, malloca. Add u32-chr,
+       u32-cmp.
+
 2023-04-02  Bruno Haible  <bruno@clisp.org>
 
        unistr/u*strstr tests: Add more tests.
index 5a21a1f63df3af842f3efcfbd04bc28d0767faba..2be6cd5744fc758494c8b779c2382b238417cd57 100644 (file)
 /* Specification.  */
 #include "unistr.h"
 
-#include "malloca.h"
-
-/* FIXME: Maybe walking the string via u16_mblen is a win?  */
-
 #define UNIT uint16_t
-
-#define CANON_ELEMENT(c) c
-#include "str-kmp.h"
-
 #define FUNC u16_strstr
-#define U_STRCHR u16_strchr
-#define U_STRMBTOUC u16_strmbtouc
-#define U_STRLEN u16_strlen
-#define U_STRNLEN u16_strnlen
-#include "u-strstr.h"
+#define RETURN_TYPE uint16_t *
+#define MEMCHR0(s, n) u16_chr (s, n, 0)
+#define STRCHR u16_strchr
+#define CMP_FUNC u16_cmp
+#include "wcsstr-impl.h"
index 261d93afb3b1cd26bac38c45c48600de1e311c1f..62f04d0cdf8916a86a72673a71b25f09ccfe6992 100644 (file)
 /* Specification.  */
 #include "unistr.h"
 
-#include "malloca.h"
-
 #define UNIT uint32_t
-
-#define CANON_ELEMENT(c) c
-#include "str-kmp.h"
-
 #define FUNC u32_strstr
-#define U_STRCHR u32_strchr
-#define U_STRLEN u32_strlen
-#define U_STRNLEN u32_strnlen
-#include "u-strstr.h"
+#define RETURN_TYPE uint32_t *
+#define MEMCHR0(s, n) u32_chr (s, n, 0)
+#define STRCHR u32_strchr
+#define CMP_FUNC u32_cmp
+#include "wcsstr-impl.h"
index 0879026f2b2c2d4e43c3fd041f73d4699e675ba7..b160f90c4ab8a1a31026211acd5335b823c1749d 100644 (file)
 
 /* Before including this file, you need to include <config.h> and
    <string.h>, and define:
+     UNIT                    The element type of the needle and haystack.
      RETURN_TYPE             A macro that expands to the return type.
      AVAILABLE(h, h_l, j, n_l)
                              A macro that returns nonzero if there are
                              at least N_L characters left starting at H[J].
-                             H is 'wchar_t *', H_L, J, and N_L
-                             are 'size_t'; H_L is an lvalue.  For
-                             NUL-terminated searches, H_L can be
-                             modified each iteration to avoid having
-                             to compute the end of H up front.
+                             H is 'UNIT *', H_L, J, and N_L are 'size_t';
+                             H_L is an lvalue.  For NUL-terminated searches,
+                             H_L can be modified each iteration to avoid
+                             having to compute the end of H up front.
 
   For case-insensitivity, you may optionally define:
      CMP_FUNC(p1, p2, l)     A macro that returns 0 iff the first L
                              characters of P1 and P2 are equal.
      CANON_ELEMENT(c)        A macro that canonicalizes an element right after
                              it has been fetched from one of the two strings.
-                             The argument is a 'wchar_t'; the result
-                             must be a 'wchar_t' as well.
+                             The argument is a 'UNIT'; the result must be a
+                             'UNIT' as well.
 
   This file undefines the macros documented above, and defines
   LONG_NEEDLE_THRESHOLD.
@@ -88,7 +88,7 @@
    suffixes are determined by lexicographic comparison while tracking
    periodicity.  */
 static size_t
-critical_factorization (const wchar_t *needle, size_t needle_len,
+critical_factorization (const UNIT *needle, size_t needle_len,
                         size_t *period)
 {
   /* Index of last character of left half, or SIZE_MAX.  */
@@ -96,7 +96,7 @@ critical_factorization (const wchar_t *needle, size_t needle_len,
   size_t j; /* Index into NEEDLE for current candidate suffix.  */
   size_t k; /* Offset into current period.  */
   size_t p; /* Intermediate period.  */
-  wchar_t a, b; /* Current comparison characters.  */
+  UNIT a, b; /* Current comparison characters.  */
 
   /* Special case NEEDLE_LEN of 1 or 2 (all callers already filtered
      out 0-length needles.  */
@@ -215,8 +215,8 @@ critical_factorization (const wchar_t *needle, size_t needle_len,
    If AVAILABLE modifies HAYSTACK_LEN (as in strstr), then at most 3 *
    HAYSTACK_LEN - NEEDLE_LEN comparisons occur in searching.  */
 static RETURN_TYPE _GL_ATTRIBUTE_PURE
-two_way_short_needle (const wchar_t *haystack, size_t haystack_len,
-                      const wchar_t *needle, size_t needle_len)
+two_way_short_needle (const UNIT *haystack, size_t haystack_len,
+                      const UNIT *needle, size_t needle_len)
 {
   size_t i; /* Index into current character of NEEDLE.  */
   size_t j; /* Index into current window of HAYSTACK.  */
@@ -300,4 +300,3 @@ two_way_short_needle (const wchar_t *haystack, size_t haystack_len,
 #undef CANON_ELEMENT
 #undef CMP_FUNC
 #undef MAX
-#undef RETURN_TYPE
index ccd64672b482124843257608e3d72937c13a5190..f889c26b11a9e672cd19ccdbe7e514ae672f0991 100644 (file)
    You should have received a copy of the GNU Lesser General Public License
    along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
 
-/* Written by Bruno Haible, 1999, and Eric Blake, 2008.  */
+/* Written by Eric Blake, 2008.  */
 
-#if NEED_LINEAR_WCSSTR
+#define AVAILABLE(h, h_l, j, n_l)                       \
+  (!MEMCHR0 ((h) + (h_l), (j) + (n_l) - (h_l))          \
+   && ((h_l) = (j) + (n_l)))
+#include "wcs-two-way.h"
 
-/* Use Two-Way algorithm, worst-case O(n+m).  */
-
-# define RETURN_TYPE wchar_t *
-# define AVAILABLE(h, h_l, j, n_l)                       \
-   (!wmemchr ((h) + (h_l), L'\0', (j) + (n_l) - (h_l))   \
-    && ((h_l) = (j) + (n_l)))
-# include "wcs-two-way.h"
-
-wchar_t *
-wcsstr (const wchar_t *haystack_start, const wchar_t *needle_start)
+RETURN_TYPE
+FUNC (const UNIT *haystack_start, const UNIT *needle_start)
 {
-  const wchar_t *haystack = haystack_start;
-  const wchar_t *needle = needle_start;
+  const UNIT *haystack = haystack_start;
+  const UNIT *needle = needle_start;
   size_t needle_len; /* Length of NEEDLE.  */
   size_t haystack_len; /* Known minimum length of HAYSTACK.  */
   bool ok = true; /* True if NEEDLE is prefix of HAYSTACK.  */
@@ -43,14 +38,14 @@ wcsstr (const wchar_t *haystack_start, const wchar_t *needle_start)
   if (*needle)
     return NULL;
   if (ok)
-    return (wchar_t *) haystack_start;
+    return (RETURN_TYPE) haystack_start;
 
-  /* Reduce the size of haystack using wcschr, since it has a smaller
+  /* Reduce the size of haystack using STRCHR, since it has a smaller
      linear coefficient than the Two-Way algorithm.  */
   needle_len = needle - needle_start;
-  haystack = wcschr (haystack_start + 1, *needle_start);
+  haystack = STRCHR (haystack_start + 1, *needle_start);
   if (!haystack || __builtin_expect (needle_len == 1, 0))
-    return (wchar_t *) haystack;
+    return (RETURN_TYPE) haystack;
   needle -= needle_len;
   haystack_len = (haystack > haystack_start + needle_len ? 1
                   : needle_len + haystack_start - haystack);
@@ -59,44 +54,3 @@ wcsstr (const wchar_t *haystack_start, const wchar_t *needle_start)
   return two_way_short_needle (haystack, haystack_len,
                                needle, needle_len);
 }
-
-#else
-
-/* Use simple implementation, worst-case O(nm).  */
-
-wchar_t *
-wcsstr (const wchar_t *haystack, const wchar_t *needle)
-{
-  wchar_t n = needle[0];
-
-  /* Is needle empty?  */
-  if (n == (wchar_t)'\0')
-    return (wchar_t *) haystack;
-
-  /* Is needle nearly empty?  */
-  if (needle[1] == (wchar_t)'\0')
-    return wcschr (haystack, n);
-
-  /* Search for needle's first character.  */
-  for (; *haystack != (wchar_t)'\0'; haystack++)
-    {
-      if (*haystack == n)
-        {
-          /* Compare with needle's remaining characters.  */
-          const wchar_t *hptr = haystack + 1;
-          const wchar_t *nptr = needle + 1;
-          for (;;)
-            {
-              if (*hptr != *nptr)
-                break;
-              hptr++; nptr++;
-              if (*nptr == (wchar_t)'\0')
-                return (wchar_t *) haystack;
-            }
-        }
-    }
-
-  return NULL;
-}
-
-#endif
index 47a947d02e7db664b83bb8cc21488eee2df84eb4..6c73f2df5fbd536acb585bc540271167ca886df8 100644 (file)
    You should have received a copy of the GNU Lesser General Public License
    along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
 
+/* Written by Bruno Haible, 1999.  */
+
 #include <config.h>
 
 /* Specification.  */
 #include <wchar.h>
 
-#include "wcsstr-impl.h"
+#if NEED_LINEAR_WCSSTR
+
+/* Use Two-Way algorithm, worst-case O(n+m).  */
+
+# define FUNC wcsstr
+# define UNIT wchar_t
+# define RETURN_TYPE wchar_t *
+# define MEMCHR0(s, n) wmemchr (s, 0, n)
+# define STRCHR wcschr
+# include "wcsstr-impl.h"
+
+#else
+
+/* Use simple implementation, worst-case O(nm).  */
+
+wchar_t *
+wcsstr (const wchar_t *haystack, const wchar_t *needle)
+{
+  wchar_t n = needle[0];
+
+  /* Is needle empty?  */
+  if (n == (wchar_t)'\0')
+    return (wchar_t *) haystack;
+
+  /* Is needle nearly empty?  */
+  if (needle[1] == (wchar_t)'\0')
+    return wcschr (haystack, n);
+
+  /* Search for needle's first character.  */
+  for (; *haystack != (wchar_t)'\0'; haystack++)
+    {
+      if (*haystack == n)
+        {
+          /* Compare with needle's remaining characters.  */
+          const wchar_t *hptr = haystack + 1;
+          const wchar_t *nptr = needle + 1;
+          for (;;)
+            {
+              if (*hptr != *nptr)
+                break;
+              hptr++; nptr++;
+              if (*nptr == (wchar_t)'\0')
+                return (wchar_t *) haystack;
+            }
+        }
+    }
+
+  return NULL;
+}
+
+#endif
index 501bee53035b30e27ee8d3bc0b547f171bf2c638..1ad2e4eec305653138a0dc61b9fc8abf1a5f71f4 100644 (file)
@@ -3,17 +3,15 @@ Substring test for UTF-16 strings.
 
 Files:
 lib/unistr/u16-strstr.c
-lib/unistr/u-strstr.h
-lib/str-kmp.h
+lib/wcsstr-impl.h
+lib/wcs-two-way.h
 
 Depends-on:
 unistr/base
+unistr/u16-chr
 unistr/u16-strchr
-unistr/u16-strmbtouc
-unistr/u16-strlen
-unistr/u16-strnlen
+unistr/u16-cmp
 stdbool
-malloca
 
 configure.ac:
 gl_LIBUNISTRING_MODULE([0.9.4], [unistr/u16-strstr])
index 1fb2fcf498fa61f3829056edc001a9a9789de945..64d95434b13e31e4d4c74ee51aac9f8803095a48 100644 (file)
@@ -3,16 +3,15 @@ Substring test for UTF-32 strings.
 
 Files:
 lib/unistr/u32-strstr.c
-lib/unistr/u-strstr.h
-lib/str-kmp.h
+lib/wcsstr-impl.h
+lib/wcs-two-way.h
 
 Depends-on:
 unistr/base
+unistr/u32-chr
 unistr/u32-strchr
-unistr/u32-strlen
-unistr/u32-strnlen
+unistr/u32-cmp
 stdbool
-malloca
 
 configure.ac:
 gl_LIBUNISTRING_MODULE([0.9.4], [unistr/u32-strstr])