123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585 |
- //
- // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
- //
- // Distributed under the Boost Software License, Version 1.0. (See accompanying
- // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
- //
- // Official repository: https://github.com/boostorg/beast
- //
- #ifndef BOOST_BEAST_HTTP_IMPL_FIELD_IPP
- #define BOOST_BEAST_HTTP_IMPL_FIELD_IPP
- #include <boost/beast/http/field.hpp>
- #include <boost/assert.hpp>
- #include <algorithm>
- #include <array>
- #include <cstring>
- #include <ostream>
- namespace boost {
- namespace beast {
- namespace http {
- namespace detail {
- struct field_table
- {
- static
- std::uint32_t
- get_chars(
- unsigned char const* p) noexcept
- {
- // VFALCO memcpy is endian-dependent
- //std::memcpy(&v, p, 4);
- // Compiler should be smart enough to
- // optimize this down to one instruction.
- return
- p[0] |
- (p[1] << 8) |
- (p[2] << 16) |
- (p[3] << 24);
- }
- using array_type =
- std::array<string_view, 357>;
- // Strings are converted to lowercase
- static
- std::uint32_t
- digest(string_view s)
- {
- std::uint32_t r = 0;
- std::size_t n = s.size();
- auto p = reinterpret_cast<
- unsigned char const*>(s.data());
- // consume N characters at a time
- // VFALCO Can we do 8 on 64-bit systems?
- while(n >= 4)
- {
- auto const v = get_chars(p);
- r = (r * 5 + (
- v | 0x20202020 )); // convert to lower
- p += 4;
- n -= 4;
- }
- // handle remaining characters
- while( n > 0 )
- {
- r = r * 5 + ( *p | 0x20 );
- ++p;
- --n;
- }
- return r;
- }
- // This comparison is case-insensitive, and the
- // strings must contain only valid http field characters.
- static
- bool
- equals(string_view lhs, string_view rhs)
- {
- using Int = std::uint32_t; // VFALCO std::size_t?
- auto n = lhs.size();
- if(n != rhs.size())
- return false;
- auto p1 = reinterpret_cast<
- unsigned char const*>(lhs.data());
- auto p2 = reinterpret_cast<
- unsigned char const*>(rhs.data());
- auto constexpr S = sizeof(Int);
- auto constexpr Mask = static_cast<Int>(
- 0xDFDFDFDFDFDFDFDF & ~Int{0});
- for(; n >= S; p1 += S, p2 += S, n -= S)
- {
- Int const v1 = get_chars(p1);
- Int const v2 = get_chars(p2);
- if((v1 ^ v2) & Mask)
- return false;
- }
- for(; n; ++p1, ++p2, --n)
- if(( *p1 ^ *p2) & 0xDF)
- return false;
- return true;
- }
- array_type by_name_;
- enum { N = 5155 };
- unsigned char map_[ N ][ 2 ] = {};
- /*
- From:
-
- https://www.iana.org/assignments/message-headers/message-headers.xhtml
- */
- field_table()
- : by_name_({{
- // string constants
- "<unknown-field>",
- "A-IM",
- "Accept",
- "Accept-Additions",
- "Accept-Charset",
- "Accept-Datetime",
- "Accept-Encoding",
- "Accept-Features",
- "Accept-Language",
- "Accept-Patch",
- "Accept-Post",
- "Accept-Ranges",
- "Access-Control",
- "Access-Control-Allow-Credentials",
- "Access-Control-Allow-Headers",
- "Access-Control-Allow-Methods",
- "Access-Control-Allow-Origin",
- "Access-Control-Expose-Headers",
- "Access-Control-Max-Age",
- "Access-Control-Request-Headers",
- "Access-Control-Request-Method",
- "Age",
- "Allow",
- "ALPN",
- "Also-Control",
- "Alt-Svc",
- "Alt-Used",
- "Alternate-Recipient",
- "Alternates",
- "Apparently-To",
- "Apply-To-Redirect-Ref",
- "Approved",
- "Archive",
- "Archived-At",
- "Article-Names",
- "Article-Updates",
- "Authentication-Control",
- "Authentication-Info",
- "Authentication-Results",
- "Authorization",
- "Auto-Submitted",
- "Autoforwarded",
- "Autosubmitted",
- "Base",
- "Bcc",
- "Body",
- "C-Ext",
- "C-Man",
- "C-Opt",
- "C-PEP",
- "C-PEP-Info",
- "Cache-Control",
- "CalDAV-Timezones",
- "Cancel-Key",
- "Cancel-Lock",
- "Cc",
- "Close",
- "Comments",
- "Compliance",
- "Connection",
- "Content-Alternative",
- "Content-Base",
- "Content-Description",
- "Content-Disposition",
- "Content-Duration",
- "Content-Encoding",
- "Content-features",
- "Content-ID",
- "Content-Identifier",
- "Content-Language",
- "Content-Length",
- "Content-Location",
- "Content-MD5",
- "Content-Range",
- "Content-Return",
- "Content-Script-Type",
- "Content-Style-Type",
- "Content-Transfer-Encoding",
- "Content-Type",
- "Content-Version",
- "Control",
- "Conversion",
- "Conversion-With-Loss",
- "Cookie",
- "Cookie2",
- "Cost",
- "DASL",
- "Date",
- "Date-Received",
- "DAV",
- "Default-Style",
- "Deferred-Delivery",
- "Delivery-Date",
- "Delta-Base",
- "Depth",
- "Derived-From",
- "Destination",
- "Differential-ID",
- "Digest",
- "Discarded-X400-IPMS-Extensions",
- "Discarded-X400-MTS-Extensions",
- "Disclose-Recipients",
- "Disposition-Notification-Options",
- "Disposition-Notification-To",
- "Distribution",
- "DKIM-Signature",
- "DL-Expansion-History",
- "Downgraded-Bcc",
- "Downgraded-Cc",
- "Downgraded-Disposition-Notification-To",
- "Downgraded-Final-Recipient",
- "Downgraded-From",
- "Downgraded-In-Reply-To",
- "Downgraded-Mail-From",
- "Downgraded-Message-Id",
- "Downgraded-Original-Recipient",
- "Downgraded-Rcpt-To",
- "Downgraded-References",
- "Downgraded-Reply-To",
- "Downgraded-Resent-Bcc",
- "Downgraded-Resent-Cc",
- "Downgraded-Resent-From",
- "Downgraded-Resent-Reply-To",
- "Downgraded-Resent-Sender",
- "Downgraded-Resent-To",
- "Downgraded-Return-Path",
- "Downgraded-Sender",
- "Downgraded-To",
- "EDIINT-Features",
- "Eesst-Version",
- "Encoding",
- "Encrypted",
- "Errors-To",
- "ETag",
- "Expect",
- "Expires",
- "Expiry-Date",
- "Ext",
- "Followup-To",
- "Forwarded",
- "From",
- "Generate-Delivery-Report",
- "GetProfile",
- "Hobareg",
- "Host",
- "HTTP2-Settings",
- "If",
- "If-Match",
- "If-Modified-Since",
- "If-None-Match",
- "If-Range",
- "If-Schedule-Tag-Match",
- "If-Unmodified-Since",
- "IM",
- "Importance",
- "In-Reply-To",
- "Incomplete-Copy",
- "Injection-Date",
- "Injection-Info",
- "Jabber-ID",
- "Keep-Alive",
- "Keywords",
- "Label",
- "Language",
- "Last-Modified",
- "Latest-Delivery-Time",
- "Lines",
- "Link",
- "List-Archive",
- "List-Help",
- "List-ID",
- "List-Owner",
- "List-Post",
- "List-Subscribe",
- "List-Unsubscribe",
- "List-Unsubscribe-Post",
- "Location",
- "Lock-Token",
- "Man",
- "Max-Forwards",
- "Memento-Datetime",
- "Message-Context",
- "Message-ID",
- "Message-Type",
- "Meter",
- "Method-Check",
- "Method-Check-Expires",
- "MIME-Version",
- "MMHS-Acp127-Message-Identifier",
- "MMHS-Authorizing-Users",
- "MMHS-Codress-Message-Indicator",
- "MMHS-Copy-Precedence",
- "MMHS-Exempted-Address",
- "MMHS-Extended-Authorisation-Info",
- "MMHS-Handling-Instructions",
- "MMHS-Message-Instructions",
- "MMHS-Message-Type",
- "MMHS-Originator-PLAD",
- "MMHS-Originator-Reference",
- "MMHS-Other-Recipients-Indicator-CC",
- "MMHS-Other-Recipients-Indicator-To",
- "MMHS-Primary-Precedence",
- "MMHS-Subject-Indicator-Codes",
- "MT-Priority",
- "Negotiate",
- "Newsgroups",
- "NNTP-Posting-Date",
- "NNTP-Posting-Host",
- "Non-Compliance",
- "Obsoletes",
- "Opt",
- "Optional",
- "Optional-WWW-Authenticate",
- "Ordering-Type",
- "Organization",
- "Origin",
- "Original-Encoded-Information-Types",
- "Original-From",
- "Original-Message-ID",
- "Original-Recipient",
- "Original-Sender",
- "Original-Subject",
- "Originator-Return-Address",
- "Overwrite",
- "P3P",
- "Path",
- "PEP",
- "Pep-Info",
- "PICS-Label",
- "Position",
- "Posting-Version",
- "Pragma",
- "Prefer",
- "Preference-Applied",
- "Prevent-NonDelivery-Report",
- "Priority",
- "Privicon",
- "ProfileObject",
- "Protocol",
- "Protocol-Info",
- "Protocol-Query",
- "Protocol-Request",
- "Proxy-Authenticate",
- "Proxy-Authentication-Info",
- "Proxy-Authorization",
- "Proxy-Connection",
- "Proxy-Features",
- "Proxy-Instruction",
- "Public",
- "Public-Key-Pins",
- "Public-Key-Pins-Report-Only",
- "Range",
- "Received",
- "Received-SPF",
- "Redirect-Ref",
- "References",
- "Referer",
- "Referer-Root",
- "Relay-Version",
- "Reply-By",
- "Reply-To",
- "Require-Recipient-Valid-Since",
- "Resent-Bcc",
- "Resent-Cc",
- "Resent-Date",
- "Resent-From",
- "Resent-Message-ID",
- "Resent-Reply-To",
- "Resent-Sender",
- "Resent-To",
- "Resolution-Hint",
- "Resolver-Location",
- "Retry-After",
- "Return-Path",
- "Safe",
- "Schedule-Reply",
- "Schedule-Tag",
- "Sec-Fetch-Dest",
- "Sec-Fetch-Mode",
- "Sec-Fetch-Site",
- "Sec-Fetch-User",
- "Sec-WebSocket-Accept",
- "Sec-WebSocket-Extensions",
- "Sec-WebSocket-Key",
- "Sec-WebSocket-Protocol",
- "Sec-WebSocket-Version",
- "Security-Scheme",
- "See-Also",
- "Sender",
- "Sensitivity",
- "Server",
- "Set-Cookie",
- "Set-Cookie2",
- "SetProfile",
- "SIO-Label",
- "SIO-Label-History",
- "SLUG",
- "SoapAction",
- "Solicitation",
- "Status-URI",
- "Strict-Transport-Security",
- "Subject",
- "SubOK",
- "Subst",
- "Summary",
- "Supersedes",
- "Surrogate-Capability",
- "Surrogate-Control",
- "TCN",
- "TE",
- "Timeout",
- "Title",
- "To",
- "Topic",
- "Trailer",
- "Transfer-Encoding",
- "TTL",
- "UA-Color",
- "UA-Media",
- "UA-Pixels",
- "UA-Resolution",
- "UA-Windowpixels",
- "Upgrade",
- "Urgency",
- "URI",
- "User-Agent",
- "Variant-Vary",
- "Vary",
- "VBR-Info",
- "Version",
- "Via",
- "Want-Digest",
- "Warning",
- "WWW-Authenticate",
- "X-Archived-At",
- "X-Device-Accept",
- "X-Device-Accept-Charset",
- "X-Device-Accept-Encoding",
- "X-Device-Accept-Language",
- "X-Device-User-Agent",
- "X-Frame-Options",
- "X-Mittente",
- "X-PGP-Sig",
- "X-Ricevuta",
- "X-Riferimento-Message-ID",
- "X-TipoRicevuta",
- "X-Trasporto",
- "X-VerificaSicurezza",
- "X400-Content-Identifier",
- "X400-Content-Return",
- "X400-Content-Type",
- "X400-MTS-Identifier",
- "X400-Originator",
- "X400-Received",
- "X400-Recipients",
- "X400-Trace",
- "Xref"
- }})
- {
- for(std::size_t i = 1, n = 256; i < n; ++i)
- {
- auto sv = by_name_[ i ];
- auto h = digest(sv);
- auto j = h % N;
- BOOST_ASSERT(map_[j][0] == 0);
- map_[j][0] = static_cast<unsigned char>(i);
- }
- for(std::size_t i = 256, n = by_name_.size(); i < n; ++i)
- {
- auto sv = by_name_[i];
- auto h = digest(sv);
- auto j = h % N;
- BOOST_ASSERT(map_[j][1] == 0);
- map_[j][1] = static_cast<unsigned char>(i - 255);
- }
- }
- field
- string_to_field(string_view s) const
- {
- auto h = digest(s);
- auto j = h % N;
- int i = map_[j][0];
- string_view s2 = by_name_[i];
- if(i != 0 && equals(s, s2))
- return static_cast<field>(i);
- i = map_[j][1];
- if(i == 0)
- return field::unknown;
- i += 255;
- s2 = by_name_[i];
- if(equals(s, s2))
- return static_cast<field>(i);
- return field::unknown;
- }
- //
- // Deprecated
- //
- using const_iterator =
- array_type::const_iterator;
- std::size_t
- size() const
- {
- return by_name_.size();
- }
- const_iterator
- begin() const
- {
- return by_name_.begin();
- }
- const_iterator
- end() const
- {
- return by_name_.end();
- }
- };
- BOOST_BEAST_DECL
- field_table const&
- get_field_table()
- {
- static field_table const tab;
- return tab;
- }
- BOOST_BEAST_DECL
- string_view
- to_string(field f)
- {
- auto const& v = get_field_table();
- BOOST_ASSERT(static_cast<unsigned>(f) < v.size());
- return v.begin()[static_cast<unsigned>(f)];
- }
- } // detail
- string_view
- to_string(field f)
- {
- return detail::to_string(f);
- }
- field
- string_to_field(string_view s)
- {
- return detail::get_field_table().string_to_field(s);
- }
- std::ostream&
- operator<<(std::ostream& os, field f)
- {
- return os << to_string(f);
- }
- } // http
- } // beast
- } // boost
- #endif
|