LCOV - code coverage report
Current view: top level - src - field.cpp (source / functions) Coverage Total Hit Missed
Test: coverage_remapped.info Lines: 92.8 % 69 64 5
Test Date: 2026-07-22 18:52:55 Functions: 90.9 % 11 10 1

           TLA  Line data    Source code
       1                 : //
       2                 : // Copyright (c) 2021 Vinnie Falco (vinnie.falco@gmail.com)
       3                 : // Copyright (c) 2025 Mohammad Nejati
       4                 : //
       5                 : // Distributed under the Boost Software License, Version 1.0. (See accompanying
       6                 : // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
       7                 : //
       8                 : // Official repository: https://github.com/cppalliance/http
       9                 : //
      10                 : 
      11                 : #include <boost/http/field.hpp>
      12                 : #include <boost/assert.hpp>
      13                 : #include <boost/core/detail/string_view.hpp>
      14                 : #include <array>
      15                 : #include <cstdint>
      16                 : #include <cstring>
      17                 : #include <ostream>
      18                 : 
      19                 : namespace boost {
      20                 : namespace http {
      21                 : 
      22                 : namespace detail {
      23                 : 
      24                 : struct field_table
      25                 : {
      26                 :     static
      27                 :     std::uint32_t
      28 HIT      105131 :     get_chars(
      29                 :         unsigned char const* p) noexcept
      30                 :     {
      31                 :         // VFALCO memcpy is endian-dependent
      32                 :         //std::memcpy(&v, p, 4);
      33                 :         // Compiler should be smart enough to
      34                 :         // optimize this down to one instruction.
      35                 :         return
      36          105131 :              p[0] |
      37          105131 :             (p[1] <<  8) |
      38          105131 :             (p[2] << 16) |
      39          105131 :             (p[3] << 24);
      40                 :     }
      41                 : 
      42                 :     using array_type = std::array<
      43                 :         core::string_view, 130>;
      44                 : 
      45                 :     // Strings are converted to lowercase
      46                 :     static
      47                 :     std::uint32_t
      48           13013 :     digest(core::string_view s)
      49                 :     {
      50           13013 :         std::uint32_t r = 0;
      51           13013 :         std::size_t n = s.size();
      52                 :         auto p = reinterpret_cast<
      53           13013 :             unsigned char const*>(s.data());
      54                 :         // consume N characters at a time
      55                 :         // VFALCO Can we do 8 on 64-bit systems?
      56           52510 :         while(n >= 4)
      57                 :         {
      58           39497 :             auto const v = get_chars(p);
      59           39497 :             r = (r * 5 + (
      60           39497 :                 v | 0x20202020 )); // convert to lower
      61           39497 :             p += 4;
      62           39497 :             n -= 4;
      63                 :         }
      64                 :         // handle remaining characters
      65           32523 :         while( n > 0 )
      66                 :         {
      67           19510 :             r = r * 5 + ( *p | 0x20 );
      68           19510 :             ++p;
      69           19510 :             --n;
      70                 :         }
      71           13013 :         return r;
      72                 :     }
      73                 : 
      74                 :     // This comparison is case-insensitive, and the
      75                 :     // strings must contain only valid http field characters.
      76                 :     static
      77                 :     bool
      78            9970 :     equals(
      79                 :         core::string_view lhs,
      80                 :         core::string_view rhs)
      81                 :     {
      82                 :         using Int = std::uint32_t; // VFALCO std::size_t?
      83            9970 :         auto n = lhs.size();
      84            9970 :         if(n != rhs.size())
      85 MIS           0 :             return false;
      86                 :         auto p1 = reinterpret_cast<
      87 HIT        9970 :             unsigned char const*>(lhs.data());
      88                 :         auto p2 = reinterpret_cast<
      89            9970 :             unsigned char const*>(rhs.data());
      90            9970 :         auto constexpr S = sizeof(Int);
      91            9970 :         auto constexpr Mask = static_cast<Int>(
      92                 :             0xDFDFDFDFDFDFDFDF & ~Int{0});
      93           42787 :         for(; n >= S; p1 += S, p2 += S, n -= S)
      94                 :         {
      95           32817 :             Int const v1 = get_chars(p1);
      96           32817 :             Int const v2 = get_chars(p2);
      97           32817 :             if((v1 ^ v2) & Mask)
      98 MIS           0 :                 return false;
      99                 :         }
     100 HIT       25363 :         for(; n; ++p1, ++p2, --n)
     101           15393 :             if(( *p1 ^ *p2) & 0xDF)
     102 MIS           0 :                 return false;
     103 HIT        9970 :         return true;
     104                 :     }
     105                 : 
     106                 :     array_type by_name_;
     107                 : 
     108                 :     enum { N = 1367 };
     109                 :     unsigned char map_[ N ] = {};
     110                 : 
     111                 : /*
     112                 :     From:
     113                 :     https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers
     114                 :     https://www.iana.org/assignments/http-fields/http-fields.xhtml
     115                 : */
     116              16 :     field_table()
     117              16 :         : by_name_({{
     118                 :             "<unknown-field>",
     119                 :             "Accept",
     120                 :             "Accept-CH",
     121                 :             "Accept-Charset",
     122                 :             "Accept-Encoding",
     123                 :             "Accept-Language",
     124                 :             "Accept-Patch",
     125                 :             "Accept-Post",
     126                 :             "Accept-Ranges",
     127                 :             "Accept-Signature",
     128                 :             "Access-Control-Allow-Credentials",
     129                 :             "Access-Control-Allow-Headers",
     130                 :             "Access-Control-Allow-Methods",
     131                 :             "Access-Control-Allow-Origin",
     132                 :             "Access-Control-Expose-Headers",
     133                 :             "Access-Control-Max-Age",
     134                 :             "Access-Control-Request-Headers",
     135                 :             "Access-Control-Request-Method",
     136                 :             "Age",
     137                 :             "Allow",
     138                 :             "Alt-Svc",
     139                 :             "Alt-Used",
     140                 :             "Authorization",
     141                 :             "Cache-Control",
     142                 :             "Clear-Site-Data",
     143                 :             "Connection",
     144                 :             "Content-Digest",
     145                 :             "Content-Disposition",
     146                 :             "Content-DPR",
     147                 :             "Content-Encoding",
     148                 :             "Content-Language",
     149                 :             "Content-Length",
     150                 :             "Content-Location",
     151                 :             "Content-Range",
     152                 :             "Content-Security-Policy",
     153                 :             "Content-Security-Policy-Report-Only",
     154                 :             "Content-Type",
     155                 :             "Cookie",
     156                 :             "Cross-Origin-Embedder-Policy",
     157                 :             "Cross-Origin-Opener-Policy",
     158                 :             "Cross-Origin-Resource-Policy",
     159                 :             "Date",
     160                 :             "Deprecation",
     161                 :             "Device-Memory",
     162                 :             "Digest",
     163                 :             "DNT",
     164                 :             "DPR",
     165                 :             "ETag",
     166                 :             "Expect",
     167                 :             "Expect-CT",
     168                 :             "Expires",
     169                 :             "Forwarded",
     170                 :             "From",
     171                 :             "Host",
     172                 :             "HTTP2-Settings",
     173                 :             "If-Match",
     174                 :             "If-Modified-Since",
     175                 :             "If-None-Match",
     176                 :             "If-Range",
     177                 :             "If-Unmodified-Since",
     178                 :             "Keep-Alive",
     179                 :             "Last-Modified",
     180                 :             "Link",
     181                 :             "Location",
     182                 :             "Max-Forwards",
     183                 :             "Origin",
     184                 :             "Origin-Agent-Cluster",
     185                 :             "Pragma",
     186                 :             "Prefer",
     187                 :             "Preference-Applied",
     188                 :             "Priority",
     189                 :             "Proxy-Authenticate",
     190                 :             "Proxy-Authorization",
     191                 :             "Proxy-Connection",
     192                 :             "Range",
     193                 :             "Referer",
     194                 :             "Referrer-Policy",
     195                 :             "Refresh",
     196                 :             "Report-To",
     197                 :             "Reporting-Endpoints",
     198                 :             "Repr-Digest",
     199                 :             "Retry-After",
     200                 :             "Sec-CH-UA-Full-Version",
     201                 :             "Sec-Fetch-Dest",
     202                 :             "Sec-Fetch-Mode",
     203                 :             "Sec-Fetch-Site",
     204                 :             "Sec-Fetch-User",
     205                 :             "Sec-Purpose",
     206                 :             "Sec-WebSocket-Accept",
     207                 :             "Sec-WebSocket-Extensions",
     208                 :             "Sec-WebSocket-Key",
     209                 :             "Sec-WebSocket-Protocol",
     210                 :             "Sec-WebSocket-Version",
     211                 :             "Server",
     212                 :             "Server-Timing",
     213                 :             "Service-Worker",
     214                 :             "Service-Worker-Allowed",
     215                 :             "Service-Worker-Navigation-Preload",
     216                 :             "Set-Cookie",
     217                 :             "Set-Login",
     218                 :             "Signature",
     219                 :             "Signature-Input",
     220                 :             "SourceMap",
     221                 :             "Strict-Transport-Security",
     222                 :             "TE",
     223                 :             "Timing-Allow-Origin",
     224                 :             "Tk",
     225                 :             "Trailer",
     226                 :             "Transfer-Encoding",
     227                 :             "Upgrade",
     228                 :             "Upgrade-Insecure-Requests",
     229                 :             "User-Agent",
     230                 :             "Vary",
     231                 :             "Via",
     232                 :             "Viewport-Width",
     233                 :             "Want-Content-Digest",
     234                 :             "Want-Repr-Digest",
     235                 :             "Warning",
     236                 :             "Width",
     237                 :             "WWW-Authenticate",
     238                 :             "X-Content-Type-Options",
     239                 :             "X-DNS-Prefetch-Control",
     240                 :             "X-Forwarded-For",
     241                 :             "X-Forwarded-Host",
     242                 :             "X-Forwarded-Proto",
     243                 :             "X-Frame-Options",
     244                 :             "X-Permitted-Cross-Domain-Policies",
     245                 :             "X-Powered-By",
     246                 :             "X-Robots-Tag",
     247                 :             "X-XSS-Protection"
     248              16 :         }})
     249                 :     {
     250            4160 :         for(std::size_t i = 1; i < by_name_.size(); ++i)
     251                 :         {
     252            2064 :             auto sv = by_name_[ i ];
     253            2064 :             auto h = digest(sv);
     254            2064 :             auto j = h % N;
     255            2064 :             BOOST_ASSERT(map_[j] == 0);
     256            2064 :             map_[j] = static_cast<unsigned char>(i);
     257                 :         }
     258              16 :     }
     259                 : 
     260                 :     optional<field>
     261           10949 :     string_to_field(
     262                 :         core::string_view s) const noexcept
     263                 :     {
     264           10949 :         auto h = digest(s);
     265           10949 :         auto j = h % N;
     266           10949 :         int i = map_[j];
     267           10949 :         if(i != 0 && equals(s, by_name_[i]))
     268            9970 :             return static_cast<field>(i);
     269             979 :         return boost::none;
     270                 :     }
     271                 : 
     272                 :     //
     273                 :     // Deprecated
     274                 :     //
     275                 : 
     276                 :     using const_iterator =
     277                 :     array_type::const_iterator; 
     278                 : 
     279                 :     std::size_t
     280             369 :     size() const
     281                 :     {
     282             738 :         return by_name_.size();
     283                 :     }
     284                 : 
     285                 :     const_iterator
     286             369 :     begin() const
     287                 :     {
     288             369 :         return by_name_.begin();
     289                 :     }
     290                 : 
     291                 :     const_iterator
     292                 :     end() const
     293                 :     {
     294                 :         return by_name_.end();
     295                 :     }
     296                 : };
     297                 : 
     298                 : static
     299                 : field_table const&
     300           11318 : get_field_table() noexcept
     301                 : {
     302           11318 :     static field_table const tab;
     303           11318 :     return tab;
     304                 : }
     305                 : 
     306                 : } // detail
     307                 : 
     308                 : core::string_view
     309             369 : to_string(field f)
     310                 : {
     311             369 :     auto const& v = detail::get_field_table();
     312             369 :     BOOST_ASSERT(static_cast<unsigned>(f) < v.size());
     313             369 :     return v.begin()[static_cast<unsigned>(f)];
     314                 : }
     315                 : 
     316                 : boost::optional<field>
     317           10949 : string_to_field(
     318                 :     core::string_view s) noexcept
     319                 : {
     320           10949 :     return detail::get_field_table().string_to_field(s);
     321                 : }
     322                 : 
     323                 : std::ostream&
     324 MIS           0 : operator<<(std::ostream& os, field f)
     325                 : {
     326               0 :     return os << to_string(f);
     327                 : }
     328                 : 
     329                 : } // http
     330                 : } // boost
        

Generated by: LCOV version 2.3