mirror of
https://github.com/curl/curl.git
synced 2026-08-26 20:53:47 +03:00
protocol: simpler Curl_getn_scheme runs faster
Iterating unit test 1627 50,000 times show the new version to be 31% faster on my machine. - unit1627: add more test strings, In particular three, five and six letter non-existing schemes. - remove scripts/schemetable.c, not used anymore Closes #22658
This commit is contained in:
parent
c2676bf9e6
commit
2687751471
7 changed files with 274 additions and 272 deletions
243
lib/protocol.c
243
lib/protocol.c
|
|
@ -462,72 +462,199 @@ const struct Curl_scheme Curl_scheme_wss = {
|
|||
PORT_HTTPS /* defport */
|
||||
};
|
||||
|
||||
|
||||
static const struct Curl_scheme *two_letter_scheme(const char *scheme)
|
||||
{
|
||||
if((Curl_raw_tolower(scheme[0]) == 'w') &&
|
||||
(Curl_raw_tolower(scheme[1]) == 's'))
|
||||
return &Curl_scheme_ws;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const struct Curl_scheme *three_letter_scheme(const char *scheme)
|
||||
{
|
||||
char s0 = Curl_raw_tolower(scheme[0]);
|
||||
char s1 = Curl_raw_tolower(scheme[1]);
|
||||
char s2 = Curl_raw_tolower(scheme[2]);
|
||||
if(s0 == 'f') {
|
||||
if(s1 == 't' && s2 == 'p')
|
||||
return &Curl_scheme_ftp;
|
||||
}
|
||||
else if(s0 == 'w') {
|
||||
if(s1 == 's' && s2 == 's')
|
||||
return &Curl_scheme_wss;
|
||||
}
|
||||
else if(s0 == 's') {
|
||||
if(s1 == 'c' && s2 == 'p')
|
||||
return &Curl_scheme_scp;
|
||||
if(s1 == 'm' && s2 == 'b')
|
||||
return &Curl_scheme_smb;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const struct Curl_scheme *four_letter_scheme(const char *scheme)
|
||||
{
|
||||
char s0 = Curl_raw_tolower(scheme[0]);
|
||||
char s1 = Curl_raw_tolower(scheme[1]);
|
||||
char s2 = Curl_raw_tolower(scheme[2]);
|
||||
char s3 = Curl_raw_tolower(scheme[3]);
|
||||
if(s3 == 'p') {
|
||||
if(s0 == 'h') {
|
||||
if(s1 == 't' && s2 == 't')
|
||||
return &Curl_scheme_http;
|
||||
}
|
||||
else if(s0 == 'i') {
|
||||
if(s1 == 'm' && s2 == 'a')
|
||||
return &Curl_scheme_imap;
|
||||
}
|
||||
else if(s0 == 'l') {
|
||||
if(s1 == 'd' && s2 == 'a')
|
||||
return &Curl_scheme_ldap;
|
||||
}
|
||||
else if(s0 == 'r') {
|
||||
if(s1 == 't' && s2 == 's')
|
||||
return &Curl_scheme_rtsp;
|
||||
}
|
||||
else if(s0 == 't') {
|
||||
if(s1 == 'f' && s2 == 't')
|
||||
return &Curl_scheme_tftp;
|
||||
}
|
||||
else if(s0 == 's') {
|
||||
if(s1 == 'f' && s2 == 't')
|
||||
return &Curl_scheme_sftp;
|
||||
if(s1 == 'm' && s2 == 't')
|
||||
return &Curl_scheme_smtp;
|
||||
}
|
||||
}
|
||||
else if(s0 == 'f') {
|
||||
if(s1 == 't' && s2 == 'p' && s3 == 's')
|
||||
return &Curl_scheme_ftps;
|
||||
if(s1 == 'i' && s2 == 'l' && s3 == 'e')
|
||||
return &Curl_scheme_file;
|
||||
}
|
||||
else if(s0 == 'm') {
|
||||
if(s1 == 'q' && s2 == 't' && s3 == 't')
|
||||
return &Curl_scheme_mqtt;
|
||||
}
|
||||
else if(s0 == 'p') {
|
||||
if(s1 == 'o' && s2 == 'p' && s3 == '3')
|
||||
return &Curl_scheme_pop3;
|
||||
}
|
||||
else if(s0 == 'd') {
|
||||
if(s1 == 'i' && s2 == 'c' && s3 == 't')
|
||||
return &Curl_scheme_dict;
|
||||
}
|
||||
else if(s0 == 's') {
|
||||
if(s1 == 'm' && s2 == 'b' && s3 == 's')
|
||||
return &Curl_scheme_smbs;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const struct Curl_scheme *five_letter_scheme(const char *scheme)
|
||||
{
|
||||
char s4 = Curl_raw_tolower(scheme[4]);
|
||||
if(s4 == 's') {
|
||||
char s0 = Curl_raw_tolower(scheme[0]);
|
||||
char s1 = Curl_raw_tolower(scheme[1]);
|
||||
char s2 = Curl_raw_tolower(scheme[2]);
|
||||
char s3 = Curl_raw_tolower(scheme[3]);
|
||||
if(s3 == 'p') {
|
||||
switch(s0) {
|
||||
case 'h':
|
||||
if(s1 == 't' && s2 == 't')
|
||||
return &Curl_scheme_https;
|
||||
break;
|
||||
case 'l':
|
||||
if(s1 == 'd' && s2 == 'a')
|
||||
return &Curl_scheme_ldaps;
|
||||
break;
|
||||
case 'i':
|
||||
if(s1 == 'm' && s2 == 'a')
|
||||
return &Curl_scheme_imaps;
|
||||
break;
|
||||
case 's':
|
||||
if(s1 == 'm' && s2 == 't')
|
||||
return &Curl_scheme_smtps;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if(s0 == 'p') {
|
||||
if(s1 == 'o' && s2 == 'p' && s3 == '3')
|
||||
return &Curl_scheme_pop3s;
|
||||
}
|
||||
else if(s0 == 'm') {
|
||||
if(s1 == 'q' && s2 == 't' && s3 == 't')
|
||||
return &Curl_scheme_mqtts;
|
||||
}
|
||||
else if(s0 == 's') {
|
||||
if(s1 == 'o' && s2 == 'c' && s3 == 'k')
|
||||
return &Curl_scheme_socks;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const struct Curl_scheme *six_letter_scheme(const char *scheme)
|
||||
{
|
||||
char s0 = Curl_raw_tolower(scheme[0]);
|
||||
switch(s0) {
|
||||
case 's':
|
||||
if(curl_strnequal("ocks4", &scheme[1], 5))
|
||||
return &Curl_scheme_socks4;
|
||||
if(curl_strnequal("ocks5", &scheme[1], 5))
|
||||
return &Curl_scheme_socks5;
|
||||
break;
|
||||
case 'g':
|
||||
if(curl_strnequal("opher", &scheme[1], 5))
|
||||
return &Curl_scheme_gopher;
|
||||
break;
|
||||
case 't':
|
||||
if(curl_strnequal("elnet", &scheme[1], 5))
|
||||
return &Curl_scheme_telnet;
|
||||
break;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const struct Curl_scheme *seven_letter_scheme(const char *scheme)
|
||||
{
|
||||
char s0 = Curl_raw_tolower(scheme[0]);
|
||||
if(s0 == 's') {
|
||||
if(curl_strnequal("ocks4a", &scheme[1], 6))
|
||||
return &Curl_scheme_socks4a;
|
||||
if(curl_strnequal("ocks5h", &scheme[1], 6))
|
||||
return &Curl_scheme_socks5h;
|
||||
}
|
||||
else if(s0 == 'g') {
|
||||
if(curl_strnequal("ophers", &scheme[1], 6))
|
||||
return &Curl_scheme_gophers;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Returns a struct scheme pointer if the name is a known scheme. Check the
|
||||
->run struct field for non-NULL to figure out if an implementation is
|
||||
present. */
|
||||
const struct Curl_scheme *Curl_getn_scheme(const char *scheme, size_t len)
|
||||
{
|
||||
/* table generated by schemetable.c:
|
||||
1. gcc schemetable.c && ./a.out
|
||||
2. check how small the table gets
|
||||
3. tweak the hash algorithm, then rerun from 1
|
||||
4. when the table is good enough
|
||||
5. copy the table into this source code
|
||||
6. make sure this function uses the same hash function that worked for
|
||||
schemetable.c
|
||||
*/
|
||||
static const struct Curl_scheme * const all_schemes[59] = { NULL,
|
||||
&Curl_scheme_pop3, NULL,
|
||||
&Curl_scheme_smtps,
|
||||
&Curl_scheme_socks,
|
||||
&Curl_scheme_socks4,
|
||||
&Curl_scheme_socks5, NULL, NULL,
|
||||
&Curl_scheme_gophers,
|
||||
&Curl_scheme_ws,
|
||||
&Curl_scheme_sftp,
|
||||
&Curl_scheme_socks4a,
|
||||
&Curl_scheme_scp,
|
||||
&Curl_scheme_rtsp,
|
||||
&Curl_scheme_dict, NULL, NULL,
|
||||
&Curl_scheme_gopher, NULL, NULL, NULL,
|
||||
&Curl_scheme_wss, NULL,
|
||||
&Curl_scheme_smb, NULL,
|
||||
&Curl_scheme_ldap,
|
||||
&Curl_scheme_ldaps,
|
||||
&Curl_scheme_imap, NULL, NULL, NULL,
|
||||
&Curl_scheme_imaps,
|
||||
&Curl_scheme_https,
|
||||
&Curl_scheme_tftp,
|
||||
&Curl_scheme_telnet, NULL, NULL, NULL,
|
||||
&Curl_scheme_file,
|
||||
&Curl_scheme_smtp, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
&Curl_scheme_ftp,
|
||||
&Curl_scheme_mqtt, NULL,
|
||||
&Curl_scheme_socks5h,
|
||||
&Curl_scheme_http,
|
||||
&Curl_scheme_pop3s, NULL,
|
||||
&Curl_scheme_mqtts, NULL,
|
||||
&Curl_scheme_smbs,
|
||||
&Curl_scheme_ftps,
|
||||
typedef const struct Curl_scheme *(*letterfunc)(const char *ptr);
|
||||
static const letterfunc parse[] = {
|
||||
two_letter_scheme,
|
||||
three_letter_scheme,
|
||||
four_letter_scheme,
|
||||
five_letter_scheme,
|
||||
six_letter_scheme,
|
||||
seven_letter_scheme
|
||||
};
|
||||
|
||||
if(len && (len <= 7)) {
|
||||
const char *s = scheme;
|
||||
size_t l = len;
|
||||
const struct Curl_scheme *h;
|
||||
unsigned int c = 443;
|
||||
while(l) {
|
||||
c <<= 5;
|
||||
c += (unsigned int)Curl_raw_tolower(*s);
|
||||
s++;
|
||||
l--;
|
||||
}
|
||||
if(len < 2 || len > 7)
|
||||
return NULL;
|
||||
|
||||
h = all_schemes[c % 59];
|
||||
if(h && curl_strnequal(scheme, h->name, len) && !h->name[len])
|
||||
return h;
|
||||
}
|
||||
return NULL;
|
||||
return parse[len - 2](scheme);
|
||||
}
|
||||
|
||||
const struct Curl_scheme *Curl_get_scheme(const char *scheme)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue