strcase: inline the raw case conversions

Curl_raw_toupper() and Curl_raw_tolower() were out-of-line functions
doing a single table lookup, and casecompare() invokes one of them twice
per byte compared, so every case-insensitive comparison in the library
paid two calls per byte: header matching, scheme and host compares,
cookie domains.

Make them static CURL_INLINE functions in strcase.h and give the two
mapping tables external linkage so the lookup inlines in every
translation unit without relying on LTO or unity mode. The tables and
the mapping they perform are unchanged, so this is not a behavior
change.

curl_strequal() on identical header names: -49% on a Cortex-A55, -51%
on a 250MHz e300c3.

Closes #22672
This commit is contained in:
Ron Kuper 2026-08-25 12:12:35 -04:00 committed by Daniel Stenberg
parent 7be1e70cb6
commit bb8ec5eb65
No known key found for this signature in database
GPG key ID: 5CC908FDB71E12C2
2 changed files with 20 additions and 18 deletions

View file

@ -26,7 +26,7 @@
#include "strcase.h"
/* Mapping table to go from lowercase to uppercase for plain ASCII.*/
static const unsigned char touppermap[256] = {
const unsigned char Curl_touppermap[256] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44,
@ -48,7 +48,7 @@ static const unsigned char touppermap[256] = {
};
/* Mapping table to go from uppercase to lowercase for plain ASCII.*/
static const unsigned char tolowermap[256] = {
const unsigned char Curl_tolowermap[256] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44,
@ -69,20 +69,6 @@ static const unsigned char tolowermap[256] = {
255
};
/* Portable, consistent toupper. Do not use toupper() because its behavior is
altered by the current locale. */
char Curl_raw_toupper(char in)
{
return (char)touppermap[(unsigned char)in];
}
/* Portable, consistent tolower. Do not use tolower() because its behavior is
altered by the current locale. */
char Curl_raw_tolower(char in)
{
return (char)tolowermap[(unsigned char)in];
}
/* Copy an upper case version of the string from src to dest. The
* strings may overlap. No more than n characters of the string are copied
* (including any NUL) and the destination string will NOT be

View file

@ -25,8 +25,24 @@
***************************************************************************/
#include "curl_setup.h"
char Curl_raw_toupper(char in);
char Curl_raw_tolower(char in);
/* Mapping tables for plain ASCII case conversion, defined in strcase.c.
Declared here so the conversions below inline at every call site without
relying on LTO or a unity build: casecompare() invokes one of them twice
per byte compared, where the call costs more than the lookup itself. */
extern const unsigned char Curl_touppermap[256];
extern const unsigned char Curl_tolowermap[256];
/* Portable, consistent toupper/tolower. Do not use toupper()/tolower() from
<ctype.h>, whose behavior is altered by the current locale. */
static CURL_INLINE char Curl_raw_toupper(char in)
{
return (char)Curl_touppermap[(unsigned char)in];
}
static CURL_INLINE char Curl_raw_tolower(char in)
{
return (char)Curl_tolowermap[(unsigned char)in];
}
/* checkprefix() is a shorter version of the above, used when the first
argument is the string literal */