diff options
Diffstat (limited to 'boost/beast/http/impl/field.ipp')
-rw-r--r-- | boost/beast/http/impl/field.ipp | 561 |
1 files changed, 561 insertions, 0 deletions
diff --git a/boost/beast/http/impl/field.ipp b/boost/beast/http/impl/field.ipp new file mode 100644 index 0000000000..8da470ff24 --- /dev/null +++ b/boost/beast/http/impl/field.ipp @@ -0,0 +1,561 @@ +// +// Copyright (c) 2016-2017 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/core/string.hpp> +#include <algorithm> +#include <array> +#include <unordered_map> +#include <vector> +#include <boost/assert.hpp> + +namespace boost { +namespace beast { +namespace http { + +namespace detail { + +struct field_table +{ + using array_type = + std::array<string_view, 352>; + + struct hash + { + std::size_t + operator()(string_view s) const + { + auto const n = s.size(); + return + beast::detail::ascii_tolower(s[0]) * + beast::detail::ascii_tolower(s[n/2]) ^ + beast::detail::ascii_tolower(s[n-1]); // hist[] = 331, 10, max_load_factor = 0.15f + } + }; + + struct iequal + { + // assumes inputs have equal length + bool + operator()( + string_view lhs, + string_view rhs) const + { + auto p1 = lhs.data(); + auto p2 = rhs.data(); + auto pend = lhs.end(); + char a, b; + while(p1 < pend) + { + a = *p1++; + b = *p2++; + if(a != b) + goto slow; + } + return true; + + while(p1 < pend) + { + slow: + if( beast::detail::ascii_tolower(a) != + beast::detail::ascii_tolower(b)) + return false; + a = *p1++; + b = *p2++; + } + return true; + } + }; + + using map_type = std::unordered_map< + string_view, field, hash, iequal>; + + array_type by_name_; + std::vector<map_type> by_size_; +/* + From: + + https://www.iana.org/assignments/message-headers/message-headers.xhtml +*/ + field_table() + : by_name_({{ + "<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-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-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" + }}) + { + // find the longest field length + std::size_t high = 0; + for(auto const& s : by_name_) + if(high < s.size()) + high = s.size(); + // build by_size map + // skip field::unknown + by_size_.resize(high + 1); + for(auto& map : by_size_) + map.max_load_factor(.15f); + for(std::size_t i = 1; + i < by_name_.size(); ++i) + { + auto const& s = by_name_[i]; + by_size_[s.size()].emplace( + s, static_cast<field>(i)); + } + +#if 0 + // This snippet calculates the performance + // of the hash function and map settings + { + std::vector<std::size_t> hist; + for(auto const& map : by_size_) + { + for(std::size_t i = 0; i < map.bucket_count(); ++i) + { + auto const n = map.bucket_size(i); + if(n > 0) + { + if(hist.size() < n) + hist.resize(n); + ++hist[n-1]; + } + } + } + } +#endif + } + + field + string_to_field(string_view s) const + { + if(s.size() >= by_size_.size()) + return field::unknown; + auto const& map = by_size_[s.size()]; + if(map.empty()) + return field::unknown; + auto it = map.find(s); + if(it == map.end()) + return field::unknown; + return it->second; + } + + // + // 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(); + } +}; + +inline +field_table const& +get_field_table() +{ + static field_table const tab; + return tab; +} + +template<class = void> +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 + +inline +string_view +to_string(field f) +{ + return detail::to_string(f); +} + +inline +field +string_to_field(string_view s) +{ + return detail::get_field_table().string_to_field(s); +} + +} // http +} // beast +} // boost + +#endif |