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