1
0
mirror of synced 2025-04-20 11:47:43 +03:00

Fixed warnings and refactoring

This commit is contained in:
yhirose 2020-09-03 18:48:56 -04:00
parent 852a374748
commit 9d12b3f20e
2 changed files with 79 additions and 97 deletions

104
httplib.h
View File

@ -1248,6 +1248,14 @@ inline std::string from_i_to_hex(size_t n) {
return ret; return ret;
} }
inline bool start_with(const std::string &a, const std::string &b) {
if (a.size() < b.size()) { return false; }
for (size_t i = 0; i < b.size(); i++) {
if (std::tolower(a[i]) != std::tolower(b[i])) { return false; }
}
return true;
}
inline size_t to_utf8(int code, char *buff) { inline size_t to_utf8(int code, char *buff) {
if (code < 0x0080) { if (code < 0x0080) {
buff[0] = (code & 0x7F); buff[0] = (code & 0x7F);
@ -1441,34 +1449,32 @@ inline std::string file_extension(const std::string &path) {
return std::string(); return std::string();
} }
inline std::pair<int, int> trim(const char *b, const char *e, int left, inline bool is_space_or_tab(char c) { return c == ' ' || c == '\t'; }
int right) {
while (b + left < e && b[left] == ' ') { inline std::pair<size_t, size_t> trim(const char *b, const char *e, size_t left,
size_t right) {
while (b + left < e && is_space_or_tab(b[left])) {
left++; left++;
} }
while (right - 1 >= 0 && b[right - 1] == ' ') { while (right > 0 && is_space_or_tab(b[right - 1])) {
right--; right--;
} }
return std::make_pair(left, right); return std::make_pair(left, right);
} }
inline void trim(std::string &s) { inline std::string trim_copy(const std::string &s) {
auto is_not_space = [](int ch) { return !std::isspace(ch); }; auto r = trim(s.data(), s.data() + s.size(), 0, s.size());
s.erase(s.begin(), std::find_if(s.begin(), s.end(), is_not_space)); return s.substr(r.first, r.second - r.first);
s.erase(std::find_if(s.rbegin(), s.rend(), is_not_space).base(), s.end());
} }
template <class Fn> void split(const char *b, const char *e, char d, Fn fn) { template <class Fn> void split(const char *b, const char *e, char d, Fn fn) {
int i = 0; size_t i = 0;
int beg = 0; size_t beg = 0;
while (e ? (b + i < e) : (b[i] != '\0')) { while (e ? (b + i < e) : (b[i] != '\0')) {
if (b[i] == d) { if (b[i] == d) {
auto r = trim(b, e, beg, i); auto r = trim(b, e, beg, i);
if (r.first < r.second) { if (r.first < r.second) { fn(&b[r.first], &b[r.second]); }
fn(&b[r.first], &b[r.second]);
}
beg = i + 1; beg = i + 1;
} }
i++; i++;
@ -1476,9 +1482,7 @@ template <class Fn> void split(const char *b, const char *e, char d, Fn fn) {
if (i) { if (i) {
auto r = trim(b, e, beg, i); auto r = trim(b, e, beg, i);
if (r.first < r.second) { if (r.first < r.second) { fn(&b[r.first], &b[r.second]); }
fn(&b[r.first], &b[r.second]);
}
} }
} }
@ -2429,26 +2433,34 @@ inline uint64_t get_header_value<uint64_t>(const Headers &headers,
return def; return def;
} }
inline void parse_header(const char *beg, const char *end, Headers &headers) { template <typename T>
inline bool parse_header(const char *beg, const char *end, T fn) {
// Skip trailing spaces and tabs.
while (beg < end && is_space_or_tab(end[-1])) {
end--;
}
auto p = beg; auto p = beg;
while (p < end && *p != ':') { while (p < end && *p != ':') {
p++; p++;
} }
if (p < end) {
if (p == end) { return false; }
auto key_end = p; auto key_end = p;
p++; // skip ':'
while (p < end && (*p == ' ' || *p == '\t')) { if (*p++ != ':') { return false; }
while (p < end && is_space_or_tab(*p)) {
p++; p++;
} }
if (p < end) { if (p < end) {
auto val_begin = p; fn(std::string(beg, key_end), decode_url(std::string(p, end), true));
while (p < end) { return true;
p++;
}
headers.emplace(std::string(beg, key_end),
decode_url(std::string(val_begin, end), true));
}
} }
return false;
} }
inline bool read_headers(Stream &strm, Headers &headers) { inline bool read_headers(Stream &strm, Headers &headers) {
@ -2467,13 +2479,13 @@ inline bool read_headers(Stream &strm, Headers &headers) {
continue; // Skip invalid line. continue; // Skip invalid line.
} }
// Skip trailing spaces and tabs. // Exclude CRLF
auto end = line_reader.ptr() + line_reader.size() - 2; auto end = line_reader.ptr() + line_reader.size() - 2;
while (line_reader.ptr() < end && (end[-1] == ' ' || end[-1] == '\t')) {
end--;
}
parse_header(line_reader.ptr(), end, headers); parse_header(line_reader.ptr(), end,
[&](std::string &&key, std::string &&val) {
headers.emplace(std::move(key), std::move(val));
});
} }
return true; return true;
@ -2835,18 +2847,6 @@ inline bool redirect(T &cli, const Request &req, Response &res,
return ret; return ret;
} }
inline bool contains_header(const std::string &header, const std::string &name) {
if (header.length() >= name.length()) {
for (int i = 0; i < name.length(); ++i) {
if (std::tolower(header[i]) != std::tolower(name[i])) {
return false;
}
}
return true;
}
return false;
}
inline std::string params_to_query_str(const Params &params) { inline std::string params_to_query_str(const Params &params) {
std::string query; std::string query;
@ -2975,15 +2975,13 @@ public:
break; break;
} }
auto header = buf_.substr(0, pos); static const std::string header_name = "content-type:";
{ const auto header = buf_.substr(0, pos);
if (start_with(header, header_name)) {
file_.content_type = trim_copy(header.substr(header_name.size()));
} else {
std::smatch m; std::smatch m;
const std::string header_name = "content-type:"; if (std::regex_match(header, m, re_content_disposition)) {
if (contains_header(header, header_name)) {
header.erase(header.begin(), header.begin() + header_name.size());
trim(header);
file_.content_type = header;
} else if (std::regex_match(header, m, re_content_disposition)) {
file_.name = m[1]; file_.name = m[1];
file_.filename = m[2]; file_.filename = m[2];
} }

View File

@ -43,22 +43,11 @@ TEST(StartupTest, WSAStartup) {
ASSERT_EQ(0, ret); ASSERT_EQ(0, ret);
} }
#endif #endif
TEST(TrimTests, TrimStringTests) { TEST(TrimTests, TrimStringTests) {
{ EXPECT_EQ("abc", detail::trim_copy("abc"));
std::string s = "abc"; EXPECT_EQ("abc", detail::trim_copy(" abc "));
detail::trim(s); EXPECT_TRUE(detail::trim_copy("").empty());
EXPECT_EQ("abc", s);
}
{
std::string s = " abc ";
detail::trim(s);
EXPECT_EQ("abc", s);
}
{
std::string s = "";
detail::trim(s);
EXPECT_TRUE( s.empty() );
}
} }
TEST(SplitTest, ParseQueryString) { TEST(SplitTest, ParseQueryString) {
@ -100,7 +89,6 @@ TEST(SplitTest, ParseInvalidQueryTests) {
} }
} }
TEST(ParseQueryTest, ParseQueryString) { TEST(ParseQueryTest, ParseQueryString) {
string s = "key1=val1&key2=val2&key3=val3"; string s = "key1=val1&key2=val2&key3=val3";
Params dic; Params dic;
@ -1827,8 +1815,7 @@ TEST_F(ServerTest, MultipartFormData) {
{"file1", "h\ne\n\nl\nl\no\n", "hello.txt", "text/plain"}, {"file1", "h\ne\n\nl\nl\no\n", "hello.txt", "text/plain"},
{"file2", "{\n \"world\", true\n}\n", "world.json", "application/json"}, {"file2", "{\n \"world\", true\n}\n", "world.json", "application/json"},
{"file3", "", "", "application/octet-stream"}, {"file3", "", "", "application/octet-stream"},
{"file4", "", "", " application/json tmp-string "} {"file4", "", "", " application/json tmp-string "}};
};
auto res = cli_.Post("/multipart", items); auto res = cli_.Post("/multipart", items);
@ -2201,7 +2188,6 @@ TEST_F(ServerTest, GetStreamedChunkedWithGzip2) {
EXPECT_EQ(std::string("123456789"), res->body); EXPECT_EQ(std::string("123456789"), res->body);
} }
TEST(GzipDecompressor, ChunkedDecompression) { TEST(GzipDecompressor, ChunkedDecompression) {
std::string data; std::string data;
for (size_t i = 0; i < 32 * 1024; ++i) { for (size_t i = 0; i < 32 * 1024; ++i) {
@ -2212,10 +2198,8 @@ TEST(GzipDecompressor, ChunkedDecompression) {
{ {
httplib::detail::gzip_compressor compressor; httplib::detail::gzip_compressor compressor;
bool result = compressor.compress( bool result = compressor.compress(
data.data(), data.data(), data.size(),
data.size(), /*last=*/true, [&](const char *data, size_t size) {
/*last=*/true,
[&] (const char* data, size_t size) {
compressed_data.insert(compressed_data.size(), data, size); compressed_data.insert(compressed_data.size(), data, size);
return true; return true;
}); });
@ -2226,14 +2210,15 @@ TEST(GzipDecompressor, ChunkedDecompression) {
{ {
httplib::detail::gzip_decompressor decompressor; httplib::detail::gzip_decompressor decompressor;
// Chunk size is chosen specificaly to have a decompressed chunk size equal to 16384 bytes // Chunk size is chosen specificaly to have a decompressed chunk size equal
// 16384 bytes is the size of decompressor output buffer // to 16384 bytes 16384 bytes is the size of decompressor output buffer
size_t chunk_size = 130; size_t chunk_size = 130;
for (size_t chunk_begin = 0; chunk_begin < compressed_data.size(); chunk_begin += chunk_size) { for (size_t chunk_begin = 0; chunk_begin < compressed_data.size();
size_t current_chunk_size = std::min(compressed_data.size() - chunk_begin, chunk_size); chunk_begin += chunk_size) {
size_t current_chunk_size =
std::min(compressed_data.size() - chunk_begin, chunk_size);
bool result = decompressor.decompress( bool result = decompressor.decompress(
compressed_data.data() + chunk_begin, compressed_data.data() + chunk_begin, current_chunk_size,
current_chunk_size,
[&](const char *data, size_t size) { [&](const char *data, size_t size) {
decompressed_data.insert(decompressed_data.size(), data, size); decompressed_data.insert(decompressed_data.size(), data, size);
return true; return true;
@ -2819,8 +2804,7 @@ TEST(StreamingTest, NoContentLengthStreaming) {
Server svr; Server svr;
svr.Get("/stream", [](const Request & /*req*/, Response &res) { svr.Get("/stream", [](const Request & /*req*/, Response &res) {
res.set_content_provider( res.set_content_provider("text/plain", [](size_t offset, DataSink &sink) {
"text/plain", [](size_t offset, DataSink &sink) {
if (offset < 6) { if (offset < 6) {
sink.os << (offset < 3 ? "a" : "b"); sink.os << (offset < 3 ? "a" : "b");
} else { } else {