Add Optional to Forward.h.
[WebKit.git] / Source / WebCore / platform / network / HTTPHeaderMap.h
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 HTTPHeaderMap {
40 public:
41     struct CommonHeader {
42         HTTPHeaderName key;
43         String value;
44
45         CommonHeader isolatedCopy() 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 operator==(const CommonHeader& other) const { return key == other.key && value == other.value; }
50     };
51
52     struct UncommonHeader {
53         String key;
54         String value;
55
56         UncommonHeader isolatedCopy() 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 operator==(const UncommonHeader& other) const { return key == other.key && value == other.value; }
61     };
62
63     typedef Vector<CommonHeader, 0, CrashOnOverflow, 6> CommonHeadersVector;
64     typedef Vector<UncommonHeader, 0, CrashOnOverflow, 0> UncommonHeadersVector;
65
66     class HTTPHeaderMapConstIterator {
67     public:
68         HTTPHeaderMapConstIterator(const HTTPHeaderMap& table, CommonHeadersVector::const_iterator commonHeadersIt, UncommonHeadersVector::const_iterator uncommonHeadersIt)
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 KeyValue {
78             String key;
79             Optional<HTTPHeaderName> keyAsHTTPHeaderName;
80             String value;
81         };
82
83         const KeyValue* get() const
84         {
85             ASSERT(*this != m_table.end());
86             return &m_keyValue;
87         }
88         const KeyValue& operator*() const { return *get(); }
89         const KeyValue* operator->() const { return get(); }
90
91         HTTPHeaderMapConstIterator& operator++()
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 operator!=(const HTTPHeaderMapConstIterator& other) const { return !(*this == other); }
104         bool operator==(const HTTPHeaderMapConstIterator& other) const
105         {
106             return m_commonHeadersIt == other.m_commonHeadersIt && m_uncommonHeadersIt == other.m_uncommonHeadersIt;
107         }
108
109     private:
110         bool updateKeyValue(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 updateKeyValue(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& m_table;
130         CommonHeadersVector::const_iterator m_commonHeadersIt;
131         UncommonHeadersVector::const_iterator m_uncommonHeadersIt;
132         KeyValue m_keyValue;
133     };
134     typedef HTTPHeaderMapConstIterator const_iterator;
135
136     WEBCORE_EXPORT HTTPHeaderMap();
137
138     // Gets a copy of the data suitable for passing to another thread.
139     WEBCORE_EXPORT HTTPHeaderMap isolatedCopy() const;
140
141     bool isEmpty() const { return m_commonHeaders.isEmpty() && m_uncommonHeaders.isEmpty(); }
142     int size() const { return m_commonHeaders.size() + m_uncommonHeaders.size(); }
143
144     void clear()
145     {
146         m_commonHeaders.clear();
147         m_uncommonHeaders.clear();
148     }
149
150     void shrinkToFit()
151     {
152         m_commonHeaders.shrinkToFit();
153         m_uncommonHeaders.shrinkToFit();
154     }
155
156     WEBCORE_EXPORT String get(const String& name) const;
157     WEBCORE_EXPORT void set(const String& name, const String& value);
158     WEBCORE_EXPORT void add(const String& name, const String& value);
159     WEBCORE_EXPORT void append(const String& name, const String& value);
160     WEBCORE_EXPORT bool contains(const String&) const;
161     bool remove(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 get(HTTPHeaderName) const;
171     void set(HTTPHeaderName, const String& value);
172     void add(HTTPHeaderName, const String& value);
173     bool addIfNotPresent(HTTPHeaderName, const String&);
174     WEBCORE_EXPORT bool contains(HTTPHeaderName) const;
175     WEBCORE_EXPORT bool remove(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 get(const char (&)[length]) const = delete;
179     template<size_t length> void set(const char (&)[length], const String&) = delete;
180     template<size_t length> bool contains(const char (&)[length]) = delete;
181     template<size_t length> bool remove(const char (&)[length]) = delete;
182
183     const CommonHeadersVector& commonHeaders() const { return m_commonHeaders; }
184     const UncommonHeadersVector& uncommonHeaders() const { return m_uncommonHeaders; }
185     CommonHeadersVector& commonHeaders() { return m_commonHeaders; }
186     UncommonHeadersVector& uncommonHeaders() { return m_uncommonHeaders; }
187
188     const_iterator begin() const { return const_iterator(*this, m_commonHeaders.begin(), m_uncommonHeaders.begin()); }
189     const_iterator end() const { return const_iterator(*this, m_commonHeaders.end(), m_uncommonHeaders.end()); }
190
191     friend bool operator==(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 operator!=(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 m_commonHeaders;
206     UncommonHeadersVector m_uncommonHeaders;
207 };
208
209 template <class Encoder>
210 void HTTPHeaderMap::CommonHeader::encode(Encoder& encoder) const
211 {
212     encoder.encodeEnum(key);
213     encoder << value;
214 }
215
216 template <class Decoder>
217 auto HTTPHeaderMap::CommonHeader::decode(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::encode(Encoder& encoder) const
231 {
232     encoder << key;
233     encoder << value;
234 }
235
236 template <class Decoder>
237 auto HTTPHeaderMap::UncommonHeader::decode(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::encode(Encoder& encoder) const
251 {
252     encoder << m_commonHeaders;
253     encoder << m_uncommonHeaders;
254 }
255
256 template <class Decoder>
257 bool HTTPHeaderMap::decode(Decoder& decoder, HTTPHeaderMap& headerMap)
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