]> git.eshelyaron.com Git - emacs.git/commitdiff
Speed up string-lessp further
authorMattias Engdegård <mattiase@acm.org>
Fri, 30 Sep 2022 11:59:45 +0000 (13:59 +0200)
committerMattias Engdegård <mattiase@acm.org>
Fri, 30 Sep 2022 14:24:44 +0000 (16:24 +0200)
* src/fns.c (Fstring_lessp): Use the memcmp fast path for ASCII-only
multibyte strings as well.  Specialise loops on argument
multibyteness.

src/fns.c

index 3e5a83d03d2a9ef22dce947822301be7487a37a0..22e66d3653d6f40487f604f79b3c3afdacb1176b 100644 (file)
--- a/src/fns.c
+++ b/src/fns.c
@@ -449,25 +449,55 @@ Symbols are also allowed; their print names are used instead.  */)
     CHECK_STRING (string2);
 
   ptrdiff_t n = min (SCHARS (string1), SCHARS (string2));
-  if (!STRING_MULTIBYTE (string1) && !STRING_MULTIBYTE (string2))
+
+  if ((!STRING_MULTIBYTE (string1) || SCHARS (string1) == SBYTES (string1))
+      && (!STRING_MULTIBYTE (string2) || SCHARS (string2) == SBYTES (string2)))
     {
-      /* Both arguments are unibyte (hot path).  */
+      /* Each argument is either unibyte or all-ASCII multibyte:
+        we can compare bytewise.
+        (Arbitrary multibyte strings cannot be compared bytewise because
+        that would give a different order for raw bytes 80..FF.)  */
       int d = memcmp (SSDATA (string1), SSDATA (string2), n);
       return d < 0 || (d == 0 && n < SCHARS (string2)) ? Qt : Qnil;
     }
-
-  ptrdiff_t i1 = 0, i1_byte = 0, i2 = 0, i2_byte = 0;
-
-  while (i1 < n)
+  else if (STRING_MULTIBYTE (string1) && STRING_MULTIBYTE (string2))
     {
-      /* When we find a mismatch, we must compare the
-        characters, not just the bytes.  */
-      int c1 = fetch_string_char_advance (string1, &i1, &i1_byte);
-      int c2 = fetch_string_char_advance (string2, &i2, &i2_byte);
-      if (c1 != c2)
-       return c1 < c2 ? Qt : Qnil;
+      ptrdiff_t i1 = 0, i1_byte = 0, i2 = 0, i2_byte = 0;
+      while (i1 < n)
+       {
+         int c1 = fetch_string_char_advance_no_check (string1, &i1, &i1_byte);
+         int c2 = fetch_string_char_advance_no_check (string2, &i2, &i2_byte);
+         if (c1 != c2)
+           return c1 < c2 ? Qt : Qnil;
+       }
+      return i1 < SCHARS (string2) ? Qt : Qnil;
+    }
+  else if (STRING_MULTIBYTE (string1))
+    {
+      /* string1 multibyte, string2 unibyte */
+      ptrdiff_t i1 = 0, i1_byte = 0, i2 = 0;
+      while (i1 < n)
+       {
+         int c1 = fetch_string_char_advance_no_check (string1, &i1, &i1_byte);
+         int c2 = SREF (string2, i2++);
+         if (c1 != c2)
+           return c1 < c2 ? Qt : Qnil;
+       }
+      return i1 < SCHARS (string2) ? Qt : Qnil;
+    }
+  else
+    {
+      /* string1 unibyte, string2 multibyte */
+      ptrdiff_t i1 = 0, i2 = 0, i2_byte = 0;
+      while (i1 < n)
+       {
+         int c1 = SREF (string1, i1++);
+         int c2 = fetch_string_char_advance_no_check (string2, &i2, &i2_byte);
+         if (c1 != c2)
+           return c1 < c2 ? Qt : Qnil;
+       }
+      return i1 < SCHARS (string2) ? Qt : Qnil;
     }
-  return i1 < SCHARS (string2) ? Qt : Qnil;
 }
 
 DEFUN ("string-version-lessp", Fstring_version_lessp,