tolower only modifies the character if there is a valid lower conversion: https://linux.die.net/man/3/tolower: ``` The value returned is that of the converted letter, or c if the conversion was not possible. ```
Both `isupper` and `tolower` are implemented with essentially the same lookup table so this doesn't even make a real fast path in the best case. Comparing the performance of the old ISTRING_HASH to the new one on all the files present in GLIBC. Data Type Old Time, New Time Alternating case -> 24985.754, 13883.422 random case -> 35211.777, 13569.051 all lower -> 18818.974, 13706.645 all upper -> 38859.454, 13506.315 All tests pass: ``` $> git clean -xf; ./bootstrap && ./configure && make check ... 977 Tests in 132 Categories Complete ... No Failures :-) ========================================================================= Regression PASSED: GNU Make 4.3.90 (x86_64-pc-linux-gnu) built with gcc ========================================================================= ``` --- src/hash.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/hash.h b/src/hash.h index 667d6508..e1aaa30e 100644 --- a/src/hash.h +++ b/src/hash.h @@ -154,7 +154,7 @@ extern void *hash_deleted_item; #define ISTRING_HASH_1(KEY, RESULT) do { \ unsigned char const *_key_ = (unsigned char const *) (KEY) - 1; \ while (*++_key_) \ - (RESULT) += ((isupper (*_key_) ? tolower (*_key_) : *_key_) << (_key_[1] & 0xf)); \ + (RESULT) += (tolower (*_key_) << (_key_[1] & 0xf)); \ } while (0) #define return_ISTRING_HASH_1(KEY) do { \ unsigned long _result_ = 0; \ @@ -165,7 +165,7 @@ extern void *hash_deleted_item; #define ISTRING_HASH_2(KEY, RESULT) do { \ unsigned char const *_key_ = (unsigned char const *) (KEY) - 1; \ while (*++_key_) \ - (RESULT) += ((isupper (*_key_) ? tolower (*_key_) : *_key_) << (_key_[1] & 0x7)); \ + (RESULT) += (tolower (*_key_) << (_key_[1] & 0x7); \ } while (0) #define return_ISTRING_HASH_2(KEY) do { \ unsigned long _result_ = 0; \ -- 2.25.1