Skip to content

Commit 8a6d834

Browse files
author
me
committed
- field_enum() don't compare with lower case, just compare. in parser, transform to lower case
- use strstr strchr where possible. It seems to be faster than string parsing using std::string_view functions
1 parent 77e4bbc commit 8a6d834

File tree

1 file changed

+36
-35
lines changed

1 file changed

+36
-35
lines changed

src/http.cpp

Lines changed: 36 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -428,19 +428,6 @@ namespace http
428428

429429
//----------------------------------------------------------------------------------------------------------------
430430

431-
constexpr char fast_ascii_tolower(const char c)
432-
{
433-
// The following is a tad faster than std::tolower(c)
434-
return (c >= 'A' && c <= 'Z') ? (c | 0x20) : c;
435-
}
436-
437-
constexpr bool case_insenstive_equals(std::string_view a, std::string_view b)
438-
{
439-
return a.size() == b.size() && std::equal(begin(a), end(a), begin(b), [](char ac, char bc) {
440-
return fast_ascii_tolower(ac) == fast_ascii_tolower(bc);
441-
});
442-
}
443-
444431
std::string_view field_label(field f)
445432
{
446433
return FIELDS[f];
@@ -449,7 +436,7 @@ namespace http
449436
field field_enum(std::string_view f)
450437
{
451438
for (unsigned int i = 0 ; i < std::size(FIELDS) ; ++i)
452-
if (case_insenstive_equals(FIELDS[i], f))
439+
if (FIELDS[i] == f)
453440
return (field)i;
454441
return unknown_field;
455442
}
@@ -979,6 +966,14 @@ namespace http
979966
return is_websocket_message(headers);
980967
}
981968

969+
//----------------------------------------------------------------------------------------------------------------
970+
971+
constexpr char fast_ascii_tolower(const char c)
972+
{
973+
// The following is a tad faster than std::tolower(c)
974+
return (c >= 'A' && c <= 'Z') ? (c | 0x20) : c;
975+
}
976+
982977
//----------------------------------------------------------------------------------------------------------------
983978

984979
template<class Message>
@@ -1017,7 +1012,7 @@ namespace http
10171012
if (buf.size() >= max_method_size)
10181013
{
10191014
std::string_view method_str(&buf[0], max_method_size);
1020-
const auto end = method_str.find(" ");
1015+
const auto end = method_str.find(' ');
10211016
const verb_type method = verb_enum(method_str.substr(0, end));
10221017

10231018
// Found
@@ -1043,16 +1038,17 @@ namespace http
10431038
// URI (Request only)
10441039
else if (state == uri)
10451040
{
1046-
const auto end = buf.find(" ");
1041+
auto* end = strchr(&buf[0], ' ');
10471042

10481043
// Found
1049-
if (end != std::string_view::npos)
1044+
if (end != nullptr)
10501045
{
1046+
const size_t len = std::distance(&buf[0], end);
10511047
if constexpr (std::is_same_v<Message, request>)
1052-
parse_url(buf.substr(0, end), msg.uri, msg.params, ec);
1048+
parse_url(std::string_view(&buf[0],len), msg.uri, msg.params, ec);
10531049

10541050
state = version;
1055-
buf.erase(begin(buf), begin(buf) + end + 1);
1051+
buf.erase(begin(buf), begin(buf) + len + 1);
10561052
}
10571053

10581054
// Not found
@@ -1104,12 +1100,13 @@ namespace http
11041100
// Status code (response only)
11051101
else if (state == status_code)
11061102
{
1107-
const auto end = buf.find(" ");
1103+
auto* end = strchr(&buf[0], ' ');
11081104

11091105
// Sufficient
1110-
if (end != std::string::npos)
1106+
if (end != nullptr)
11111107
{
1112-
buf[end] = '\0';
1108+
const size_t len = std::distance(&buf[0], end);
1109+
*end = '\0';
11131110
int status{-1};
11141111
const int ret = sscanf(&buf[0], "%i", &status);
11151112

@@ -1119,7 +1116,7 @@ namespace http
11191116
if constexpr (std::is_same_v<Message, response>)
11201117
msg.status = (status_type)status;
11211118
state = status_msg;
1122-
buf.erase(begin(buf), begin(buf) + end + 1);
1119+
buf.erase(begin(buf), begin(buf) + len + 1);
11231120
}
11241121

11251122
// Not found
@@ -1135,13 +1132,13 @@ namespace http
11351132
// Status label
11361133
else if (state == status_msg)
11371134
{
1138-
const auto end = buf.find("\r\n");
1135+
auto* end = strstr(&buf[0], "\r\n");
11391136

11401137
// Sufficient
1141-
if (end != std::string::npos)
1138+
if (end != nullptr)
11421139
{
11431140
state = header_line;
1144-
buf.erase(begin(buf), begin(buf) + end + 2);
1141+
buf.erase(begin(buf), begin(buf) + std::distance(&buf[0], end) + 2);
11451142
}
11461143

11471144
// Insufficient
@@ -1152,24 +1149,28 @@ namespace http
11521149
// Header line
11531150
else if (state == header_line)
11541151
{
1155-
const auto end = buf.find("\r\n");
1152+
auto* end = strstr(&buf[0], "\r\n");
11561153

11571154
// Sufficient
1158-
if (end != std::string::npos)
1155+
if (end != nullptr)
11591156
{
1157+
const size_t line_length = std::distance(&buf[0], end);
1158+
11601159
// Found header
1161-
if (end > 0)
1160+
if (line_length > 0)
11621161
{
1163-
std::string_view line(&buf[0], end);
1164-
const auto kend = line.find(": ");
1162+
auto* kend = strstr(&buf[0], ": ");
11651163

1166-
if (kend == std::string_view::npos)
1164+
if (kend == nullptr)
11671165
ec = make_error_code(http_read_header_kv_delimiter_not_found);
11681166

11691167
else
11701168
{
1171-
auto field = field_enum(line.substr(0, kend));
1172-
auto value = line.substr(kend+2);
1169+
for (auto* ptr = &buf[0] ; ptr != kend ; ++ptr)
1170+
*ptr = fast_ascii_tolower(*ptr);
1171+
1172+
auto field = field_enum(std::string_view(&buf[0], std::distance(&buf[0], kend)));
1173+
auto value = std::string_view(kend+2, std::distance(kend+2, end));
11731174

11741175
if (field == unknown_field)
11751176
ec = make_error_code(http_read_header_unsupported_field);
@@ -1196,7 +1197,7 @@ namespace http
11961197
state = done;
11971198
}
11981199

1199-
buf.erase(begin(buf), begin(buf) + end + 2);
1200+
buf.erase(begin(buf), begin(buf) + line_length + 2);
12001201
}
12011202

12021203
// Insufficient

0 commit comments

Comments
 (0)