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