@@ -321,6 +321,8 @@ make_unique(std::size_t n) {
321321 return std::unique_ptr<T>(new RT[n]);
322322}
323323
324+ namespace case_ignore {
325+
324326inline unsigned char to_lower (int c) {
325327 const static unsigned char table[256 ] = {
326328 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 , 12 , 13 , 14 ,
@@ -345,28 +347,36 @@ inline unsigned char to_lower(int c) {
345347 return table[(unsigned char )(char )c];
346348}
347349
348- struct case_ignore_equal {
349- bool operator ()(const std::string &s1, const std::string &s2) const {
350- return s1.size () == s2.size () &&
351- std::equal (s1.begin (), s1.end (), s2.begin (), [](char a, char b) {
352- return to_lower (a) == to_lower (b);
353- });
350+ inline bool equal (const std::string &a, const std::string &b) {
351+ return a.size () == b.size () &&
352+ std::equal (a.begin (), a.end (), b.begin (),
353+ [](char a, char b) { return to_lower (a) == to_lower (b); });
354+ }
355+
356+ struct equal_to {
357+ bool operator ()(const std::string &a, const std::string &b) const {
358+ return equal (a, b);
354359 }
355360};
356361
357- struct case_ignore_hash {
362+ struct hash {
358363 size_t operator ()(const std::string &key) const {
359364 return hash_core (key.data (), key.size (), 0 );
360365 }
361366
362- constexpr size_t hash_core (const char *s, size_t l, size_t h) const {
363- return (l == 0 )
364- ? h
365- : hash_core (s + 1 , l - 1 ,
366- (h * 33 ) ^ static_cast <unsigned char >(to_lower (*s)));
367+ size_t hash_core (const char *s, size_t l, size_t h) const {
368+ return (l == 0 ) ? h
369+ : hash_core (s + 1 , l - 1 ,
370+ // Unsets the 6 high bits of h, therefore no
371+ // overflow happens
372+ (((std::numeric_limits<size_t >::max)() >> 6 ) &
373+ h * 33 ) ^
374+ static_cast <unsigned char >(to_lower (*s)));
367375 }
368376};
369377
378+ }; // namespace case_ignore
379+
370380// This is based on
371381// "http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4189".
372382
@@ -473,8 +483,8 @@ enum StatusCode {
473483};
474484
475485using Headers =
476- std::unordered_multimap<std::string, std::string, detail::case_ignore_hash ,
477- detail::case_ignore_equal >;
486+ std::unordered_multimap<std::string, std::string, detail::case_ignore::hash ,
487+ detail::case_ignore::equal_to >;
478488
479489using Params = std::multimap<std::string, std::string>;
480490using Match = std::smatch;
@@ -3996,14 +4006,6 @@ inline const char *get_header_value(const Headers &headers,
39964006 return def;
39974007}
39984008
3999- inline bool compare_case_ignore (const std::string &a, const std::string &b) {
4000- if (a.size () != b.size ()) { return false ; }
4001- for (size_t i = 0 ; i < b.size (); i++) {
4002- if (to_lower (a[i]) != to_lower (b[i])) { return false ; }
4003- }
4004- return true ;
4005- }
4006-
40074009template <typename T>
40084010inline bool parse_header (const char *beg, const char *end, T fn) {
40094011 // Skip trailing spaces and tabs.
@@ -4031,7 +4033,7 @@ inline bool parse_header(const char *beg, const char *end, T fn) {
40314033 if (!key_len) { return false ; }
40324034
40334035 auto key = std::string (beg, key_end);
4034- auto val = compare_case_ignore (key, " Location" )
4036+ auto val = case_ignore::equal (key, " Location" )
40354037 ? std::string (p, end)
40364038 : decode_url (std::string (p, end), false );
40374039
@@ -4196,7 +4198,7 @@ inline bool read_content_chunked(Stream &strm, T &x,
41964198}
41974199
41984200inline bool is_chunked_transfer_encoding (const Headers &headers) {
4199- return compare_case_ignore (
4201+ return case_ignore::equal (
42004202 get_header_value (headers, " Transfer-Encoding" , " " , 0 ), " chunked" );
42014203}
42024204
@@ -4835,7 +4837,9 @@ class MultipartFormDataParser {
48354837 const std::string &b) const {
48364838 if (a.size () < b.size ()) { return false ; }
48374839 for (size_t i = 0 ; i < b.size (); i++) {
4838- if (to_lower (a[i]) != to_lower (b[i])) { return false ; }
4840+ if (case_ignore::to_lower (a[i]) != case_ignore::to_lower (b[i])) {
4841+ return false ;
4842+ }
48394843 }
48404844 return true ;
48414845 }
0 commit comments