LCOV - code coverage report
Current view: top level - src - field.cpp (source / functions) Coverage Total Hit Missed
Test: coverage_remapped.info Lines: 94.0 % 83 78 5
Test Date: 2026-06-13 19:44:58 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      117605 :     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          117605 :              p[0] |
      37          117605 :             (p[1] <<  8) |
      38          117605 :             (p[2] << 16) |
      39          117605 :             (p[3] << 24);
      40                 :     }
      41                 : 
      42                 :     using array_type = std::array<
      43                 :         core::string_view, 357>;
      44                 : 
      45                 :     // Strings are converted to lowercase
      46                 :     static
      47                 :     std::uint32_t
      48           16840 :     digest(core::string_view s)
      49                 :     {
      50           16840 :         std::uint32_t r = 0;
      51           16840 :         std::size_t n = s.size();
      52                 :         auto p = reinterpret_cast<
      53           16840 :             unsigned char const*>(s.data());
      54                 :         // consume N characters at a time
      55                 :         // VFALCO Can we do 8 on 64-bit systems?
      56           67663 :         while(n >= 4)
      57                 :         {
      58           50823 :             auto const v = get_chars(p);
      59           50823 :             r = (r * 5 + (
      60           50823 :                 v | 0x20202020 )); // convert to lower
      61           50823 :             p += 4;
      62           50823 :             n -= 4;
      63                 :         }
      64                 :         // handle remaining characters
      65           41934 :         while( n > 0 )
      66                 :         {
      67           25094 :             r = r * 5 + ( *p | 0x20 );
      68           25094 :             ++p;
      69           25094 :             --n;
      70                 :         }
      71           16840 :         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           10170 :     equals(
      79                 :         core::string_view lhs,
      80                 :         core::string_view rhs)
      81                 :     {
      82                 :         using Int = std::uint32_t; // VFALCO std::size_t?
      83           10170 :         auto n = lhs.size();
      84           10170 :         if(n != rhs.size())
      85               5 :             return false;
      86                 :         auto p1 = reinterpret_cast<
      87           10165 :             unsigned char const*>(lhs.data());
      88                 :         auto p2 = reinterpret_cast<
      89           10165 :             unsigned char const*>(rhs.data());
      90           10165 :         auto constexpr S = sizeof(Int);
      91           10165 :         auto constexpr Mask = static_cast<Int>(
      92                 :             0xDFDFDFDFDFDFDFDF & ~Int{0});
      93           43556 :         for(; n >= S; p1 += S, p2 += S, n -= S)
      94                 :         {
      95           33391 :             Int const v1 = get_chars(p1);
      96           33391 :             Int const v2 = get_chars(p2);
      97           33391 :             if((v1 ^ v2) & Mask)
      98 MIS           0 :                 return false;
      99                 :         }
     100 HIT       25830 :         for(; n; ++p1, ++p2, --n)
     101           15665 :             if(( *p1 ^ *p2) & 0xDF)
     102 MIS           0 :                 return false;
     103 HIT       10165 :         return true;
     104                 :     }
     105                 : 
     106                 :     array_type by_name_;
     107                 : 
     108                 :     enum { N = 5155 };
     109                 :     unsigned char map_[ N ][ 2 ] = {};
     110                 : 
     111                 : /*
     112                 :     From:
     113                 :     
     114                 :     https://www.iana.org/assignments/message-headers/message-headers.xhtml
     115                 : */
     116              16 :     field_table()
     117              16 :         : by_name_({{
     118                 : // string constants
     119                 : "<unknown-field>",
     120                 : "A-IM",
     121                 : "Accept",
     122                 : "Accept-Additions",
     123                 : "Accept-Charset",
     124                 : "Accept-Datetime",
     125                 : "Accept-Encoding",
     126                 : "Accept-Features",
     127                 : "Accept-Language",
     128                 : "Accept-Patch",
     129                 : "Accept-Post",
     130                 : "Accept-Ranges",
     131                 : "Access-Control",
     132                 : "Access-Control-Allow-Credentials",
     133                 : "Access-Control-Allow-Headers",
     134                 : "Access-Control-Allow-Methods",
     135                 : "Access-Control-Allow-Origin",
     136                 : "Access-Control-Expose-Headers",
     137                 : "Access-Control-Max-Age",
     138                 : "Access-Control-Request-Headers",
     139                 : "Access-Control-Request-Method",
     140                 : "Age",
     141                 : "Allow",
     142                 : "ALPN",
     143                 : "Also-Control",
     144                 : "Alt-Svc",
     145                 : "Alt-Used",
     146                 : "Alternate-Recipient",
     147                 : "Alternates",
     148                 : "Apparently-To",
     149                 : "Apply-To-Redirect-Ref",
     150                 : "Approved",
     151                 : "Archive",
     152                 : "Archived-At",
     153                 : "Article-Names",
     154                 : "Article-Updates",
     155                 : "Authentication-Control",
     156                 : "Authentication-Info",
     157                 : "Authentication-Results",
     158                 : "Authorization",
     159                 : "Auto-Submitted",
     160                 : "Autoforwarded",
     161                 : "Autosubmitted",
     162                 : "Base",
     163                 : "Bcc",
     164                 : "Body",
     165                 : "C-Ext",
     166                 : "C-Man",
     167                 : "C-Opt",
     168                 : "C-PEP",
     169                 : "C-PEP-Info",
     170                 : "Cache-Control",
     171                 : "CalDAV-Timezones",
     172                 : "Cancel-Key",
     173                 : "Cancel-Lock",
     174                 : "Cc",
     175                 : "Close",
     176                 : "Comments",
     177                 : "Compliance",
     178                 : "Connection",
     179                 : "Content-Alternative",
     180                 : "Content-Base",
     181                 : "Content-Description",
     182                 : "Content-Disposition",
     183                 : "Content-Duration",
     184                 : "Content-Encoding",
     185                 : "Content-features",
     186                 : "Content-ID",
     187                 : "Content-Identifier",
     188                 : "Content-Language",
     189                 : "Content-Length",
     190                 : "Content-Location",
     191                 : "Content-MD5",
     192                 : "Content-Range",
     193                 : "Content-Return",
     194                 : "Content-Script-Type",
     195                 : "Content-Style-Type",
     196                 : "Content-Transfer-Encoding",
     197                 : "Content-Type",
     198                 : "Content-Version",
     199                 : "Control",
     200                 : "Conversion",
     201                 : "Conversion-With-Loss",
     202                 : "Cookie",
     203                 : "Cookie2",
     204                 : "Cost",
     205                 : "DASL",
     206                 : "Date",
     207                 : "Date-Received",
     208                 : "DAV",
     209                 : "Default-Style",
     210                 : "Deferred-Delivery",
     211                 : "Delivery-Date",
     212                 : "Delta-Base",
     213                 : "Depth",
     214                 : "Derived-From",
     215                 : "Destination",
     216                 : "Differential-ID",
     217                 : "Digest",
     218                 : "Discarded-X400-IPMS-Extensions",
     219                 : "Discarded-X400-MTS-Extensions",
     220                 : "Disclose-Recipients",
     221                 : "Disposition-Notification-Options",
     222                 : "Disposition-Notification-To",
     223                 : "Distribution",
     224                 : "DKIM-Signature",
     225                 : "DL-Expansion-History",
     226                 : "Downgraded-Bcc",
     227                 : "Downgraded-Cc",
     228                 : "Downgraded-Disposition-Notification-To",
     229                 : "Downgraded-Final-Recipient",
     230                 : "Downgraded-From",
     231                 : "Downgraded-In-Reply-To",
     232                 : "Downgraded-Mail-From",
     233                 : "Downgraded-Message-Id",
     234                 : "Downgraded-Original-Recipient",
     235                 : "Downgraded-Rcpt-To",
     236                 : "Downgraded-References",
     237                 : "Downgraded-Reply-To",
     238                 : "Downgraded-Resent-Bcc",
     239                 : "Downgraded-Resent-Cc",
     240                 : "Downgraded-Resent-From",
     241                 : "Downgraded-Resent-Reply-To",
     242                 : "Downgraded-Resent-Sender",
     243                 : "Downgraded-Resent-To",
     244                 : "Downgraded-Return-Path",
     245                 : "Downgraded-Sender",
     246                 : "Downgraded-To",
     247                 : "EDIINT-Features",
     248                 : "Eesst-Version",
     249                 : "Encoding",
     250                 : "Encrypted",
     251                 : "Errors-To",
     252                 : "ETag",
     253                 : "Expect",
     254                 : "Expires",
     255                 : "Expiry-Date",
     256                 : "Ext",
     257                 : "Followup-To",
     258                 : "Forwarded",
     259                 : "From",
     260                 : "Generate-Delivery-Report",
     261                 : "GetProfile",
     262                 : "Hobareg",
     263                 : "Host",
     264                 : "HTTP2-Settings",
     265                 : "If",
     266                 : "If-Match",
     267                 : "If-Modified-Since",
     268                 : "If-None-Match",
     269                 : "If-Range",
     270                 : "If-Schedule-Tag-Match",
     271                 : "If-Unmodified-Since",
     272                 : "IM",
     273                 : "Importance",
     274                 : "In-Reply-To",
     275                 : "Incomplete-Copy",
     276                 : "Injection-Date",
     277                 : "Injection-Info",
     278                 : "Jabber-ID",
     279                 : "Keep-Alive",
     280                 : "Keywords",
     281                 : "Label",
     282                 : "Language",
     283                 : "Last-Modified",
     284                 : "Latest-Delivery-Time",
     285                 : "Lines",
     286                 : "Link",
     287                 : "List-Archive",
     288                 : "List-Help",
     289                 : "List-ID",
     290                 : "List-Owner",
     291                 : "List-Post",
     292                 : "List-Subscribe",
     293                 : "List-Unsubscribe",
     294                 : "List-Unsubscribe-Post",
     295                 : "Location",
     296                 : "Lock-Token",
     297                 : "Man",
     298                 : "Max-Forwards",
     299                 : "Memento-Datetime",
     300                 : "Message-Context",
     301                 : "Message-ID",
     302                 : "Message-Type",
     303                 : "Meter",
     304                 : "Method-Check",
     305                 : "Method-Check-Expires",
     306                 : "MIME-Version",
     307                 : "MMHS-Acp127-Message-Identifier",
     308                 : "MMHS-Authorizing-Users",
     309                 : "MMHS-Codress-Message-Indicator",
     310                 : "MMHS-Copy-Precedence",
     311                 : "MMHS-Exempted-Address",
     312                 : "MMHS-Extended-Authorisation-Info",
     313                 : "MMHS-Handling-Instructions",
     314                 : "MMHS-Message-Instructions",
     315                 : "MMHS-Message-Type",
     316                 : "MMHS-Originator-PLAD",
     317                 : "MMHS-Originator-Reference",
     318                 : "MMHS-Other-Recipients-Indicator-CC",
     319                 : "MMHS-Other-Recipients-Indicator-To",
     320                 : "MMHS-Primary-Precedence",
     321                 : "MMHS-Subject-Indicator-Codes",
     322                 : "MT-Priority",
     323                 : "Negotiate",
     324                 : "Newsgroups",
     325                 : "NNTP-Posting-Date",
     326                 : "NNTP-Posting-Host",
     327                 : "Non-Compliance",
     328                 : "Obsoletes",
     329                 : "Opt",
     330                 : "Optional",
     331                 : "Optional-WWW-Authenticate",
     332                 : "Ordering-Type",
     333                 : "Organization",
     334                 : "Origin",
     335                 : "Original-Encoded-Information-Types",
     336                 : "Original-From",
     337                 : "Original-Message-ID",
     338                 : "Original-Recipient",
     339                 : "Original-Sender",
     340                 : "Original-Subject",
     341                 : "Originator-Return-Address",
     342                 : "Overwrite",
     343                 : "P3P",
     344                 : "Path",
     345                 : "PEP",
     346                 : "Pep-Info",
     347                 : "PICS-Label",
     348                 : "Position",
     349                 : "Posting-Version",
     350                 : "Pragma",
     351                 : "Prefer",
     352                 : "Preference-Applied",
     353                 : "Prevent-NonDelivery-Report",
     354                 : "Priority",
     355                 : "Privicon",
     356                 : "ProfileObject",
     357                 : "Protocol",
     358                 : "Protocol-Info",
     359                 : "Protocol-Query",
     360                 : "Protocol-Request",
     361                 : "Proxy-Authenticate",
     362                 : "Proxy-Authentication-Info",
     363                 : "Proxy-Authorization",
     364                 : "Proxy-Connection",
     365                 : "Proxy-Features",
     366                 : "Proxy-Instruction",
     367                 : "Public",
     368                 : "Public-Key-Pins",
     369                 : "Public-Key-Pins-Report-Only",
     370                 : "Range",
     371                 : "Received",
     372                 : "Received-SPF",
     373                 : "Redirect-Ref",
     374                 : "References",
     375                 : "Referer",
     376                 : "Referer-Root",
     377                 : "Relay-Version",
     378                 : "Reply-By",
     379                 : "Reply-To",
     380                 : "Require-Recipient-Valid-Since",
     381                 : "Resent-Bcc",
     382                 : "Resent-Cc",
     383                 : "Resent-Date",
     384                 : "Resent-From",
     385                 : "Resent-Message-ID",
     386                 : "Resent-Reply-To",
     387                 : "Resent-Sender",
     388                 : "Resent-To",
     389                 : "Resolution-Hint",
     390                 : "Resolver-Location",
     391                 : "Retry-After",
     392                 : "Return-Path",
     393                 : "Safe",
     394                 : "Schedule-Reply",
     395                 : "Schedule-Tag",
     396                 : "Sec-Fetch-Dest",
     397                 : "Sec-Fetch-Mode",
     398                 : "Sec-Fetch-Site",
     399                 : "Sec-Fetch-User",
     400                 : "Sec-WebSocket-Accept",
     401                 : "Sec-WebSocket-Extensions",
     402                 : "Sec-WebSocket-Key",
     403                 : "Sec-WebSocket-Protocol",
     404                 : "Sec-WebSocket-Version",
     405                 : "Security-Scheme",
     406                 : "See-Also",
     407                 : "Sender",
     408                 : "Sensitivity",
     409                 : "Server",
     410                 : "Set-Cookie",
     411                 : "Set-Cookie2",
     412                 : "SetProfile",
     413                 : "SIO-Label",
     414                 : "SIO-Label-History",
     415                 : "SLUG",
     416                 : "SoapAction",
     417                 : "Solicitation",
     418                 : "Status-URI",
     419                 : "Strict-Transport-Security",
     420                 : "Subject",
     421                 : "SubOK",
     422                 : "Subst",
     423                 : "Summary",
     424                 : "Supersedes",
     425                 : "Surrogate-Capability",
     426                 : "Surrogate-Control",
     427                 : "TCN",
     428                 : "TE",
     429                 : "Timeout",
     430                 : "Title",
     431                 : "To",
     432                 : "Topic",
     433                 : "Trailer",
     434                 : "Transfer-Encoding",
     435                 : "TTL",
     436                 : "UA-Color",
     437                 : "UA-Media",
     438                 : "UA-Pixels",
     439                 : "UA-Resolution",
     440                 : "UA-Windowpixels",
     441                 : "Upgrade",
     442                 : "Urgency",
     443                 : "URI",
     444                 : "User-Agent",
     445                 : "Variant-Vary",
     446                 : "Vary",
     447                 : "VBR-Info",
     448                 : "Version",
     449                 : "Via",
     450                 : "Want-Digest",
     451                 : "Warning",
     452                 : "WWW-Authenticate",
     453                 : "X-Archived-At",
     454                 : "X-Device-Accept",
     455                 : "X-Device-Accept-Charset",
     456                 : "X-Device-Accept-Encoding",
     457                 : "X-Device-Accept-Language",
     458                 : "X-Device-User-Agent",
     459                 : "X-Frame-Options",
     460                 : "X-Mittente",
     461                 : "X-PGP-Sig",
     462                 : "X-Ricevuta",
     463                 : "X-Riferimento-Message-ID",
     464                 : "X-TipoRicevuta",
     465                 : "X-Trasporto",
     466                 : "X-VerificaSicurezza",
     467                 : "X400-Content-Identifier",
     468                 : "X400-Content-Return",
     469                 : "X400-Content-Type",
     470                 : "X400-MTS-Identifier",
     471                 : "X400-Originator",
     472                 : "X400-Received",
     473                 : "X400-Recipients",
     474                 : "X400-Trace",
     475                 : "Xref"
     476              16 :         }})
     477                 :     {
     478            4096 :         for(std::size_t i = 1, n = 256; i < n; ++i)
     479                 :         {
     480            4080 :             auto sv = by_name_[ i ];
     481            4080 :             auto h = digest(sv);
     482            4080 :             auto j = h % N;
     483            4080 :             BOOST_ASSERT(map_[j][0] == 0);
     484            4080 :             map_[j][0] = static_cast<unsigned char>(i);
     485                 :         }
     486                 : 
     487            1648 :         for(std::size_t i = 256, n = by_name_.size(); i < n; ++i)
     488                 :         {
     489            1616 :             auto sv = by_name_[i];
     490            1616 :             auto h = digest(sv);
     491            1616 :             auto j = h % N;
     492            1616 :             BOOST_ASSERT(map_[j][1] == 0);
     493            1616 :             map_[j][1] = static_cast<unsigned char>(i - 255);
     494                 :         }
     495              16 :     }
     496                 : 
     497                 :     optional<field>
     498           11144 :     string_to_field(
     499                 :         core::string_view s) const noexcept
     500                 :     {
     501           11144 :         auto h = digest(s);
     502           11144 :         auto j = h % N;
     503           11144 :         int i = map_[j][0];
     504           11144 :         core::string_view s2 = by_name_[i];
     505           11144 :         if(i != 0 && equals(s, s2))
     506            5027 :             return static_cast<field>(i);
     507            6117 :         i = map_[j][1];
     508            6117 :         if(i == 0)
     509             979 :             return boost::none;
     510            5138 :         i += 255;
     511            5138 :         s2 = by_name_[i];
     512                 : 
     513            5138 :         if(equals(s, s2))
     514            5138 :             return static_cast<field>(i);
     515 MIS           0 :         return boost::none;
     516                 :     }
     517                 : 
     518                 :     //
     519                 :     // Deprecated
     520                 :     //
     521                 : 
     522                 :     using const_iterator =
     523                 :     array_type::const_iterator; 
     524                 : 
     525                 :     std::size_t
     526 HIT         596 :     size() const
     527                 :     {
     528            1192 :         return by_name_.size();
     529                 :     }
     530                 : 
     531                 :     const_iterator
     532             596 :     begin() const
     533                 :     {
     534             596 :         return by_name_.begin();
     535                 :     }
     536                 : 
     537                 :     const_iterator
     538                 :     end() const
     539                 :     {
     540                 :         return by_name_.end();
     541                 :     }
     542                 : };
     543                 : 
     544                 : static
     545                 : field_table const&
     546           11740 : get_field_table() noexcept
     547                 : {
     548           11740 :     static field_table const tab;
     549           11740 :     return tab;
     550                 : }
     551                 : 
     552                 : } // detail
     553                 : 
     554                 : core::string_view
     555             596 : to_string(field f)
     556                 : {
     557             596 :     auto const& v = detail::get_field_table();
     558             596 :     BOOST_ASSERT(static_cast<unsigned>(f) < v.size());
     559             596 :     return v.begin()[static_cast<unsigned>(f)];
     560                 : }
     561                 : 
     562                 : boost::optional<field>
     563           11144 : string_to_field(
     564                 :     core::string_view s) noexcept
     565                 : {
     566           11144 :     return detail::get_field_table().string_to_field(s);
     567                 : }
     568                 : 
     569                 : std::ostream&
     570 MIS           0 : operator<<(std::ostream& os, field f)
     571                 : {
     572               0 :     return os << to_string(f);
     573                 : }
     574                 : 
     575                 : } // http
     576                 : } // boost
        

Generated by: LCOV version 2.3