diff options
| author | Mattias EngdegÄrd | 2022-09-30 13:59:45 +0200 |
|---|---|---|
| committer | Mattias EngdegÄrd | 2022-09-30 16:24:44 +0200 |
| commit | 123506f9ca33bbca57baeac74ebe7aaf462eddc5 (patch) | |
| tree | 128fd654d3ed09282c5d5b791ae48888f31f607f /src | |
| parent | b858acde25160631ce7e0e13adc579ca1a4135fb (diff) | |
| download | emacs-123506f9ca33bbca57baeac74ebe7aaf462eddc5.tar.gz emacs-123506f9ca33bbca57baeac74ebe7aaf462eddc5.zip | |
Speed up string-lessp further
* src/fns.c (Fstring_lessp): Use the memcmp fast path for ASCII-only
multibyte strings as well. Specialise loops on argument
multibyteness.
Diffstat (limited to 'src')
| -rw-r--r-- | src/fns.c | 56 |
1 files changed, 43 insertions, 13 deletions
| @@ -449,25 +449,55 @@ Symbols are also allowed; their print names are used instead. */) | |||
| 449 | CHECK_STRING (string2); | 449 | CHECK_STRING (string2); |
| 450 | 450 | ||
| 451 | ptrdiff_t n = min (SCHARS (string1), SCHARS (string2)); | 451 | ptrdiff_t n = min (SCHARS (string1), SCHARS (string2)); |
| 452 | if (!STRING_MULTIBYTE (string1) && !STRING_MULTIBYTE (string2)) | 452 | |
| 453 | if ((!STRING_MULTIBYTE (string1) || SCHARS (string1) == SBYTES (string1)) | ||
| 454 | && (!STRING_MULTIBYTE (string2) || SCHARS (string2) == SBYTES (string2))) | ||
| 453 | { | 455 | { |
| 454 | /* Both arguments are unibyte (hot path). */ | 456 | /* Each argument is either unibyte or all-ASCII multibyte: |
| 457 | we can compare bytewise. | ||
| 458 | (Arbitrary multibyte strings cannot be compared bytewise because | ||
| 459 | that would give a different order for raw bytes 80..FF.) */ | ||
| 455 | int d = memcmp (SSDATA (string1), SSDATA (string2), n); | 460 | int d = memcmp (SSDATA (string1), SSDATA (string2), n); |
| 456 | return d < 0 || (d == 0 && n < SCHARS (string2)) ? Qt : Qnil; | 461 | return d < 0 || (d == 0 && n < SCHARS (string2)) ? Qt : Qnil; |
| 457 | } | 462 | } |
| 458 | 463 | else if (STRING_MULTIBYTE (string1) && STRING_MULTIBYTE (string2)) | |
| 459 | ptrdiff_t i1 = 0, i1_byte = 0, i2 = 0, i2_byte = 0; | ||
| 460 | |||
| 461 | while (i1 < n) | ||
| 462 | { | 464 | { |
| 463 | /* When we find a mismatch, we must compare the | 465 | ptrdiff_t i1 = 0, i1_byte = 0, i2 = 0, i2_byte = 0; |
| 464 | characters, not just the bytes. */ | 466 | while (i1 < n) |
| 465 | int c1 = fetch_string_char_advance (string1, &i1, &i1_byte); | 467 | { |
| 466 | int c2 = fetch_string_char_advance (string2, &i2, &i2_byte); | 468 | int c1 = fetch_string_char_advance_no_check (string1, &i1, &i1_byte); |
| 467 | if (c1 != c2) | 469 | int c2 = fetch_string_char_advance_no_check (string2, &i2, &i2_byte); |
| 468 | return c1 < c2 ? Qt : Qnil; | 470 | if (c1 != c2) |
| 471 | return c1 < c2 ? Qt : Qnil; | ||
| 472 | } | ||
| 473 | return i1 < SCHARS (string2) ? Qt : Qnil; | ||
| 474 | } | ||
| 475 | else if (STRING_MULTIBYTE (string1)) | ||
| 476 | { | ||
| 477 | /* string1 multibyte, string2 unibyte */ | ||
| 478 | ptrdiff_t i1 = 0, i1_byte = 0, i2 = 0; | ||
| 479 | while (i1 < n) | ||
| 480 | { | ||
| 481 | int c1 = fetch_string_char_advance_no_check (string1, &i1, &i1_byte); | ||
| 482 | int c2 = SREF (string2, i2++); | ||
| 483 | if (c1 != c2) | ||
| 484 | return c1 < c2 ? Qt : Qnil; | ||
| 485 | } | ||
| 486 | return i1 < SCHARS (string2) ? Qt : Qnil; | ||
| 487 | } | ||
| 488 | else | ||
| 489 | { | ||
| 490 | /* string1 unibyte, string2 multibyte */ | ||
| 491 | ptrdiff_t i1 = 0, i2 = 0, i2_byte = 0; | ||
| 492 | while (i1 < n) | ||
| 493 | { | ||
| 494 | int c1 = SREF (string1, i1++); | ||
| 495 | int c2 = fetch_string_char_advance_no_check (string2, &i2, &i2_byte); | ||
| 496 | if (c1 != c2) | ||
| 497 | return c1 < c2 ? Qt : Qnil; | ||
| 498 | } | ||
| 499 | return i1 < SCHARS (string2) ? Qt : Qnil; | ||
| 469 | } | 500 | } |
| 470 | return i1 < SCHARS (string2) ? Qt : Qnil; | ||
| 471 | } | 501 | } |
| 472 | 502 | ||
| 473 | DEFUN ("string-version-lessp", Fstring_version_lessp, | 503 | DEFUN ("string-version-lessp", Fstring_version_lessp, |