Replace CaseFoldingHash with ASCIICaseInsensitiveHash
[WebKit-https.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 #ifndef HTTPHeaderMap_h
28 #define HTTPHeaderMap_h
29
30 #include "HTTPHeaderNames.h"
31 #include <utility>
32 #include <wtf/HashMap.h>
33 #include <wtf/Optional.h>
34 #include <wtf/Vector.h>
35 #include <wtf/text/AtomicString.h>
36 #include <wtf/text/AtomicStringHash.h>
37 #include <wtf/text/StringHash.h>
38
39 namespace WebCore {
40
41 struct CrossThreadHTTPHeaderMapData {
42     Vector<std::pair<HTTPHeaderName, String>> commonHeaders;
43     Vector<std::pair<String, String>> uncommonHeaders;
44 };
45
46 // FIXME: Not every header fits into a map. Notably, multiple Set-Cookie header fields are needed to set multiple cookies.
47
48 class HTTPHeaderMap {
49 public:
50     typedef HashMap<HTTPHeaderName, String, WTF::IntHash<HTTPHeaderName>, WTF::StrongEnumHashTraits<HTTPHeaderName>> CommonHeadersHashMap;
51     typedef HashMap<String, String, ASCIICaseInsensitiveHash> UncommonHeadersHashMap;
52
53     class HTTPHeaderMapConstIterator {
54     public:
55         HTTPHeaderMapConstIterator(const HTTPHeaderMap& table, CommonHeadersHashMap::const_iterator commonHeadersIt, UncommonHeadersHashMap::const_iterator uncommonHeadersIt)
56             : m_table(table)
57             , m_commonHeadersIt(commonHeadersIt)
58             , m_uncommonHeadersIt(uncommonHeadersIt)
59         {
60             if (!updateKeyValue(m_commonHeadersIt))
61                 updateKeyValue(m_uncommonHeadersIt);
62         }
63
64         struct KeyValue {
65             String key;
66             Optional<HTTPHeaderName> keyAsHTTPHeaderName;
67             String value;
68         };
69
70         const KeyValue* get() const
71         {
72             ASSERT(*this != m_table.end());
73             return &m_keyValue;
74         }
75         const KeyValue& operator*() const { return *get(); }
76         const KeyValue* operator->() const { return get(); }
77
78         HTTPHeaderMapConstIterator& operator++()
79         {
80             if (m_commonHeadersIt != m_table.m_commonHeaders.end()) {
81                 if (updateKeyValue(++m_commonHeadersIt))
82                     return *this;
83             } else
84                 ++m_uncommonHeadersIt;
85
86             updateKeyValue(m_uncommonHeadersIt);
87             return *this;
88         }
89
90         bool operator!=(const HTTPHeaderMapConstIterator& other) const { return !(*this == other); }
91         bool operator==(const HTTPHeaderMapConstIterator& other) const
92         {
93             return m_commonHeadersIt == other.m_commonHeadersIt && m_uncommonHeadersIt == other.m_uncommonHeadersIt;
94         }
95
96     private:
97         bool updateKeyValue(CommonHeadersHashMap::const_iterator it)
98         {
99             if (it == m_table.commonHeaders().end())
100                 return false;
101             m_keyValue.key = httpHeaderNameString(it->key).toStringWithoutCopying();
102             m_keyValue.keyAsHTTPHeaderName = it->key;
103             m_keyValue.value = it->value;
104             return true;
105         }
106         bool updateKeyValue(UncommonHeadersHashMap::const_iterator it)
107         {
108             if (it == m_table.uncommonHeaders().end())
109                 return false;
110             m_keyValue.key = it->key;
111             m_keyValue.keyAsHTTPHeaderName = Nullopt;
112             m_keyValue.value = it->value;
113             return true;
114         }
115
116         const HTTPHeaderMap& m_table;
117         CommonHeadersHashMap::const_iterator m_commonHeadersIt;
118         UncommonHeadersHashMap::const_iterator m_uncommonHeadersIt;
119         KeyValue m_keyValue;
120     };
121     typedef HTTPHeaderMapConstIterator const_iterator;
122
123     WEBCORE_EXPORT HTTPHeaderMap();
124     WEBCORE_EXPORT ~HTTPHeaderMap();
125
126     // Gets a copy of the data suitable for passing to another thread.
127     std::unique_ptr<CrossThreadHTTPHeaderMapData> copyData() const;
128     void adopt(std::unique_ptr<CrossThreadHTTPHeaderMapData>);
129
130     bool isEmpty() const { return m_commonHeaders.isEmpty() && m_uncommonHeaders.isEmpty(); }
131     int size() const { return m_commonHeaders.size() + m_uncommonHeaders.size(); }
132
133     void clear()
134     {
135         m_commonHeaders.clear();
136         m_uncommonHeaders.clear();
137     }
138
139     WEBCORE_EXPORT String get(const String& name) const;
140     WEBCORE_EXPORT void set(const String& name, const String& value);
141     void add(const String& name, const String& value);
142     bool contains(const String&) const;
143     bool remove(const String&);
144
145     WEBCORE_EXPORT String get(HTTPHeaderName) const;
146     void set(HTTPHeaderName, const String& value);
147     void add(HTTPHeaderName, const String& value);
148     bool contains(HTTPHeaderName) const;
149     WEBCORE_EXPORT bool remove(HTTPHeaderName);
150
151     // Instead of passing a string literal to any of these functions, just use a HTTPHeaderName instead.
152     template<size_t length> String get(const char (&)[length]) const = delete;
153     template<size_t length> void set(const char (&)[length], const String&) = delete;
154     template<size_t length> bool contains(const char (&)[length]) = delete;
155     template<size_t length> bool remove(const char (&)[length]) = delete;
156
157     const CommonHeadersHashMap& commonHeaders() const { return m_commonHeaders; }
158     const UncommonHeadersHashMap& uncommonHeaders() const { return m_uncommonHeaders; }
159     CommonHeadersHashMap& commonHeaders() { return m_commonHeaders; }
160     UncommonHeadersHashMap& uncommonHeaders() { return m_uncommonHeaders; }
161
162     const_iterator begin() const { return const_iterator(*this, m_commonHeaders.begin(), m_uncommonHeaders.begin()); }
163     const_iterator end() const { return const_iterator(*this, m_commonHeaders.end(), m_uncommonHeaders.end()); }
164
165     friend bool operator==(const HTTPHeaderMap& a, const HTTPHeaderMap& b)
166     {
167         return a.m_commonHeaders == b.m_commonHeaders && a.m_uncommonHeaders == b.m_uncommonHeaders;
168     }
169
170     friend bool operator!=(const HTTPHeaderMap& a, const HTTPHeaderMap& b)
171     {
172         return !(a == b);
173     }
174
175     template <class Encoder> void encode(Encoder&) const;
176     template <class Decoder> static bool decode(Decoder&, HTTPHeaderMap&);
177
178 private:
179     CommonHeadersHashMap m_commonHeaders;
180     UncommonHeadersHashMap m_uncommonHeaders;
181 };
182
183 template <class Encoder>
184 void HTTPHeaderMap::encode(Encoder& encoder) const
185 {
186     encoder << static_cast<uint64_t>(m_commonHeaders.size());
187     for (const auto& keyValuePair : m_commonHeaders) {
188         encoder.encodeEnum(keyValuePair.key);
189         encoder << keyValuePair.value;
190     }
191
192     encoder << m_uncommonHeaders;
193 }
194
195 template <class Decoder>
196 bool HTTPHeaderMap::decode(Decoder& decoder, HTTPHeaderMap& headerMap)
197 {
198     uint64_t commonHeadersSize;
199     if (!decoder.decode(commonHeadersSize))
200         return false;
201     for (size_t i = 0; i < commonHeadersSize; ++i) {
202         HTTPHeaderName name;
203         if (!decoder.decodeEnum(name))
204             return false;
205         String value;
206         if (!decoder.decode(value))
207             return false;
208         headerMap.m_commonHeaders.add(name, value);
209     }
210
211     if (!decoder.decode(headerMap.m_uncommonHeaders))
212         return false;
213
214     return true;
215 }
216
217 } // namespace WebCore
218
219 #endif // HTTPHeaderMap_h