1 | /* |
2 | * Copyright (C) 2006 Apple Inc. All rights reserved. |
3 | * Copyright (C) 2009 Google Inc. All rights reserved. |
4 | * |
5 | * Redistribution and use in source and binary forms, with or without |
6 | * modification, are permitted provided that the following conditions |
7 | * are met: |
8 | * 1. Redistributions of source code must retain the above copyright |
9 | * notice, this list of conditions and the following disclaimer. |
10 | * 2. Redistributions in binary form must reproduce the above copyright |
11 | * notice, this list of conditions and the following disclaimer in the |
12 | * documentation and/or other materials provided with the distribution. |
13 | * |
14 | * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY |
15 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
16 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
17 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR |
18 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
19 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
20 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
21 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
22 | * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
24 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
25 | */ |
26 | |
27 | #pragma once |
28 | |
29 | #include "HTTPHeaderNames.h" |
30 | #include <utility> |
31 | #include <wtf/HashMap.h> |
32 | #include <wtf/Optional.h> |
33 | #include <wtf/text/StringHash.h> |
34 | |
35 | namespace WebCore { |
36 | |
37 | // FIXME: Not every header fits into a map. Notably, multiple Set-Cookie header fields are needed to set multiple cookies. |
38 | |
39 | class { |
40 | public: |
41 | struct { |
42 | HTTPHeaderName ; |
43 | String ; |
44 | |
45 | CommonHeader () const { return { key , value.isolatedCopy() }; } |
46 | template <class Encoder> void encode(Encoder&) const; |
47 | template <class Decoder> static Optional<CommonHeader> decode(Decoder&); |
48 | |
49 | bool (const CommonHeader& other) const { return key == other.key && value == other.value; } |
50 | }; |
51 | |
52 | struct { |
53 | String ; |
54 | String ; |
55 | |
56 | UncommonHeader () const { return { key.isolatedCopy() , value.isolatedCopy() }; } |
57 | template <class Encoder> void encode(Encoder&) const; |
58 | template <class Decoder> static Optional<UncommonHeader> decode(Decoder&); |
59 | |
60 | bool (const UncommonHeader& other) const { return key == other.key && value == other.value; } |
61 | }; |
62 | |
63 | typedef Vector<CommonHeader, 0, CrashOnOverflow, 6> ; |
64 | typedef Vector<UncommonHeader, 0, CrashOnOverflow, 0> ; |
65 | |
66 | class { |
67 | public: |
68 | (const HTTPHeaderMap& table, CommonHeadersVector::const_iterator , UncommonHeadersVector::const_iterator ) |
69 | : m_table(table) |
70 | , m_commonHeadersIt(commonHeadersIt) |
71 | , m_uncommonHeadersIt(uncommonHeadersIt) |
72 | { |
73 | if (!updateKeyValue(m_commonHeadersIt)) |
74 | updateKeyValue(m_uncommonHeadersIt); |
75 | } |
76 | |
77 | struct { |
78 | String ; |
79 | Optional<HTTPHeaderName> ; |
80 | String ; |
81 | }; |
82 | |
83 | const KeyValue* () const |
84 | { |
85 | ASSERT(*this != m_table.end()); |
86 | return &m_keyValue; |
87 | } |
88 | const KeyValue& () const { return *get(); } |
89 | const KeyValue* () const { return get(); } |
90 | |
91 | HTTPHeaderMapConstIterator& () |
92 | { |
93 | if (m_commonHeadersIt != m_table.m_commonHeaders.end()) { |
94 | if (updateKeyValue(++m_commonHeadersIt)) |
95 | return *this; |
96 | } else |
97 | ++m_uncommonHeadersIt; |
98 | |
99 | updateKeyValue(m_uncommonHeadersIt); |
100 | return *this; |
101 | } |
102 | |
103 | bool (const HTTPHeaderMapConstIterator& other) const { return !(*this == other); } |
104 | bool (const HTTPHeaderMapConstIterator& other) const |
105 | { |
106 | return m_commonHeadersIt == other.m_commonHeadersIt && m_uncommonHeadersIt == other.m_uncommonHeadersIt; |
107 | } |
108 | |
109 | private: |
110 | bool (CommonHeadersVector::const_iterator it) |
111 | { |
112 | if (it == m_table.commonHeaders().end()) |
113 | return false; |
114 | m_keyValue.key = httpHeaderNameString(it->key).toStringWithoutCopying(); |
115 | m_keyValue.keyAsHTTPHeaderName = it->key; |
116 | m_keyValue.value = it->value; |
117 | return true; |
118 | } |
119 | bool (UncommonHeadersVector::const_iterator it) |
120 | { |
121 | if (it == m_table.uncommonHeaders().end()) |
122 | return false; |
123 | m_keyValue.key = it->key; |
124 | m_keyValue.keyAsHTTPHeaderName = WTF::nullopt; |
125 | m_keyValue.value = it->value; |
126 | return true; |
127 | } |
128 | |
129 | const HTTPHeaderMap& ; |
130 | CommonHeadersVector::const_iterator ; |
131 | UncommonHeadersVector::const_iterator ; |
132 | KeyValue ; |
133 | }; |
134 | typedef HTTPHeaderMapConstIterator ; |
135 | |
136 | WEBCORE_EXPORT (); |
137 | |
138 | // Gets a copy of the data suitable for passing to another thread. |
139 | WEBCORE_EXPORT HTTPHeaderMap () const; |
140 | |
141 | bool () const { return m_commonHeaders.isEmpty() && m_uncommonHeaders.isEmpty(); } |
142 | int () const { return m_commonHeaders.size() + m_uncommonHeaders.size(); } |
143 | |
144 | void () |
145 | { |
146 | m_commonHeaders.clear(); |
147 | m_uncommonHeaders.clear(); |
148 | } |
149 | |
150 | void () |
151 | { |
152 | m_commonHeaders.shrinkToFit(); |
153 | m_uncommonHeaders.shrinkToFit(); |
154 | } |
155 | |
156 | WEBCORE_EXPORT String (const String& name) const; |
157 | WEBCORE_EXPORT void (const String& name, const String& value); |
158 | WEBCORE_EXPORT void (const String& name, const String& value); |
159 | WEBCORE_EXPORT void (const String& name, const String& value); |
160 | WEBCORE_EXPORT bool (const String&) const; |
161 | bool (const String&); |
162 | |
163 | #if USE(CF) |
164 | void set(CFStringRef name, const String& value); |
165 | #ifdef __OBJC__ |
166 | void set(NSString *name, const String& value) { set((__bridge CFStringRef)name, value); } |
167 | #endif |
168 | #endif |
169 | |
170 | WEBCORE_EXPORT String (HTTPHeaderName) const; |
171 | void (HTTPHeaderName, const String& value); |
172 | void (HTTPHeaderName, const String& value); |
173 | bool (HTTPHeaderName, const String&); |
174 | WEBCORE_EXPORT bool (HTTPHeaderName) const; |
175 | WEBCORE_EXPORT bool (HTTPHeaderName); |
176 | |
177 | // Instead of passing a string literal to any of these functions, just use a HTTPHeaderName instead. |
178 | template<size_t length> String (const char (&)[length]) const = delete; |
179 | template<size_t length> void (const char (&)[length], const String&) = delete; |
180 | template<size_t length> bool (const char (&)[length]) = delete; |
181 | template<size_t length> bool (const char (&)[length]) = delete; |
182 | |
183 | const CommonHeadersVector& () const { return m_commonHeaders; } |
184 | const UncommonHeadersVector& () const { return m_uncommonHeaders; } |
185 | CommonHeadersVector& () { return m_commonHeaders; } |
186 | UncommonHeadersVector& () { return m_uncommonHeaders; } |
187 | |
188 | const_iterator () const { return const_iterator(*this, m_commonHeaders.begin(), m_uncommonHeaders.begin()); } |
189 | const_iterator () const { return const_iterator(*this, m_commonHeaders.end(), m_uncommonHeaders.end()); } |
190 | |
191 | friend bool (const HTTPHeaderMap& a, const HTTPHeaderMap& b) |
192 | { |
193 | return a.m_commonHeaders == b.m_commonHeaders && a.m_uncommonHeaders == b.m_uncommonHeaders; |
194 | } |
195 | |
196 | friend bool (const HTTPHeaderMap& a, const HTTPHeaderMap& b) |
197 | { |
198 | return !(a == b); |
199 | } |
200 | |
201 | template <class Encoder> void encode(Encoder&) const; |
202 | template <class Decoder> static bool decode(Decoder&, HTTPHeaderMap&); |
203 | |
204 | private: |
205 | CommonHeadersVector ; |
206 | UncommonHeadersVector ; |
207 | }; |
208 | |
209 | template <class Encoder> |
210 | void HTTPHeaderMap::CommonHeader::(Encoder& encoder) const |
211 | { |
212 | encoder.encodeEnum(key); |
213 | encoder << value; |
214 | } |
215 | |
216 | template <class Decoder> |
217 | auto HTTPHeaderMap::CommonHeader::(Decoder& decoder) -> Optional<CommonHeader> |
218 | { |
219 | HTTPHeaderName name; |
220 | if (!decoder.decodeEnum(name)) |
221 | return WTF::nullopt; |
222 | String value; |
223 | if (!decoder.decode(value)) |
224 | return WTF::nullopt; |
225 | |
226 | return CommonHeader { name, WTFMove(value) }; |
227 | } |
228 | |
229 | template <class Encoder> |
230 | void HTTPHeaderMap::UncommonHeader::(Encoder& encoder) const |
231 | { |
232 | encoder << key; |
233 | encoder << value; |
234 | } |
235 | |
236 | template <class Decoder> |
237 | auto HTTPHeaderMap::UncommonHeader::(Decoder& decoder) -> Optional<UncommonHeader> |
238 | { |
239 | String name; |
240 | if (!decoder.decode(name)) |
241 | return WTF::nullopt; |
242 | String value; |
243 | if (!decoder.decode(value)) |
244 | return WTF::nullopt; |
245 | |
246 | return UncommonHeader { WTFMove(name), WTFMove(value) }; |
247 | } |
248 | |
249 | template <class Encoder> |
250 | void HTTPHeaderMap::(Encoder& encoder) const |
251 | { |
252 | encoder << m_commonHeaders; |
253 | encoder << m_uncommonHeaders; |
254 | } |
255 | |
256 | template <class Decoder> |
257 | bool HTTPHeaderMap::(Decoder& decoder, HTTPHeaderMap& ) |
258 | { |
259 | if (!decoder.decode(headerMap.m_commonHeaders)) |
260 | return false; |
261 | |
262 | if (!decoder.decode(headerMap.m_uncommonHeaders)) |
263 | return false; |
264 | |
265 | return true; |
266 | } |
267 | |
268 | } // namespace WebCore |
269 | |