Add WTF::move()
[WebKit-https.git] / Source / WebKit2 / Platform / IPC / ArgumentCoders.h
1 /*
2  * Copyright (C) 2010 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #ifndef SimpleArgumentCoder_h
27 #define SimpleArgumentCoder_h
28
29 #include "ArgumentDecoder.h"
30 #include "ArgumentEncoder.h"
31 #include <utility>
32 #include <wtf/Forward.h>
33 #include <wtf/HashMap.h>
34 #include <wtf/HashSet.h>
35 #include <wtf/Optional.h>
36 #include <wtf/Vector.h>
37
38 namespace IPC {
39
40 // An argument coder works on POD types
41 template<typename T> struct SimpleArgumentCoder {
42     static void encode(ArgumentEncoder& encoder, const T& t)
43     {
44         encoder.encodeFixedLengthData(reinterpret_cast<const uint8_t*>(&t), sizeof(T), alignof(T));
45     }
46
47     static bool decode(ArgumentDecoder& decoder, T& t)
48     {
49         return decoder.decodeFixedLengthData(reinterpret_cast<uint8_t*>(&t), sizeof(T), alignof(T));
50     }
51 };
52
53 template<typename T> struct ArgumentCoder<WTF::Optional<T>> {
54     static void encode(ArgumentEncoder& encoder, const WTF::Optional<T>& optional)
55     {
56         if (!optional) {
57             encoder << false;
58             return;
59         }
60
61         encoder << true;
62         encoder << optional.value();
63     }
64
65     static bool decode(ArgumentDecoder& decoder, WTF::Optional<T>& optional)
66     {
67         bool isEngaged;
68         if (!decoder.decode(isEngaged))
69             return false;
70
71         if (!isEngaged) {
72             optional = Nullopt;
73             return true;
74         }
75
76         T value;
77         if (!decoder.decode(value))
78             return false;
79
80         optional = WTF::move(value);
81         return true;
82     }
83 };
84
85 template<typename T, typename U> struct ArgumentCoder<std::pair<T, U>> {
86     static void encode(ArgumentEncoder& encoder, const std::pair<T, U>& pair)
87     {
88         encoder << pair.first << pair.second;
89     }
90
91     static bool decode(ArgumentDecoder& decoder, std::pair<T, U>& pair)
92     {
93         T first;
94         if (!decoder.decode(first))
95             return false;
96
97         U second;
98         if (!decoder.decode(second))
99             return false;
100
101         pair.first = first;
102         pair.second = second;
103         return true;
104     }
105 };
106
107 template<typename KeyType, typename ValueType> struct ArgumentCoder<WTF::KeyValuePair<KeyType, ValueType>> {
108     static void encode(ArgumentEncoder& encoder, const WTF::KeyValuePair<KeyType, ValueType>& pair)
109     {
110         encoder << pair.key << pair.value;
111     }
112
113     static bool decode(ArgumentDecoder& decoder, WTF::KeyValuePair<KeyType, ValueType>& pair)
114     {
115         KeyType key;
116         if (!decoder.decode(key))
117             return false;
118
119         ValueType value;
120         if (!decoder.decode(value))
121             return false;
122
123         pair.key = key;
124         pair.value = value;
125         return true;
126     }
127 };
128
129 template<bool fixedSizeElements, typename T, size_t inlineCapacity> struct VectorArgumentCoder;
130
131 template<typename T, size_t inlineCapacity> struct VectorArgumentCoder<false, T, inlineCapacity> {
132     static void encode(ArgumentEncoder& encoder, const Vector<T, inlineCapacity>& vector)
133     {
134         encoder << static_cast<uint64_t>(vector.size());
135         for (size_t i = 0; i < vector.size(); ++i)
136             encoder << vector[i];
137     }
138
139     static bool decode(ArgumentDecoder& decoder, Vector<T, inlineCapacity>& vector)
140     {
141         uint64_t size;
142         if (!decoder.decode(size))
143             return false;
144
145         Vector<T, inlineCapacity> tmp;
146         for (size_t i = 0; i < size; ++i) {
147             T element;
148             if (!decoder.decode(element))
149                 return false;
150             
151             tmp.append(WTF::move(element));
152         }
153
154         tmp.shrinkToFit();
155         vector.swap(tmp);
156         return true;
157     }
158 };
159
160 template<typename T, size_t inlineCapacity> struct VectorArgumentCoder<true, T, inlineCapacity> {
161     static void encode(ArgumentEncoder& encoder, const Vector<T, inlineCapacity>& vector)
162     {
163         encoder << static_cast<uint64_t>(vector.size());
164         encoder.encodeFixedLengthData(reinterpret_cast<const uint8_t*>(vector.data()), vector.size() * sizeof(T), alignof(T));
165     }
166     
167     static bool decode(ArgumentDecoder& decoder, Vector<T, inlineCapacity>& vector)
168     {
169         uint64_t size;
170         if (!decoder.decode(size))
171             return false;
172
173         // Since we know the total size of the elements, we can allocate the vector in
174         // one fell swoop. Before allocating we must however make sure that the decoder buffer
175         // is big enough.
176         if (!decoder.bufferIsLargeEnoughToContain<T>(size)) {
177             decoder.markInvalid();
178             return false;
179         }
180
181         Vector<T, inlineCapacity> temp;
182         temp.resize(size);
183
184         decoder.decodeFixedLengthData(reinterpret_cast<uint8_t*>(temp.data()), size * sizeof(T), alignof(T));
185
186         vector.swap(temp);
187         return true;
188     }
189 };
190
191 template<typename T, size_t inlineCapacity> struct ArgumentCoder<Vector<T, inlineCapacity>> : VectorArgumentCoder<std::is_arithmetic<T>::value, T, inlineCapacity> { };
192
193 template<typename KeyArg, typename MappedArg, typename HashArg, typename KeyTraitsArg, typename MappedTraitsArg> struct ArgumentCoder<HashMap<KeyArg, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg>> {
194     typedef HashMap<KeyArg, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg> HashMapType;
195
196     static void encode(ArgumentEncoder& encoder, const HashMapType& hashMap)
197     {
198         encoder << static_cast<uint64_t>(hashMap.size());
199         for (typename HashMapType::const_iterator it = hashMap.begin(), end = hashMap.end(); it != end; ++it)
200             encoder << *it;
201     }
202
203     static bool decode(ArgumentDecoder& decoder, HashMapType& hashMap)
204     {
205         uint64_t hashMapSize;
206         if (!decoder.decode(hashMapSize))
207             return false;
208
209         HashMapType tempHashMap;
210         for (uint64_t i = 0; i < hashMapSize; ++i) {
211             KeyArg key;
212             MappedArg value;
213             if (!decoder.decode(key))
214                 return false;
215             if (!decoder.decode(value))
216                 return false;
217
218             if (!tempHashMap.add(key, value).isNewEntry) {
219                 // The hash map already has the specified key, bail.
220                 decoder.markInvalid();
221                 return false;
222             }
223         }
224
225         hashMap.swap(tempHashMap);
226         return true;
227     }
228 };
229
230 template<typename KeyArg, typename HashArg, typename KeyTraitsArg> struct ArgumentCoder<HashSet<KeyArg, HashArg, KeyTraitsArg>> {
231     typedef HashSet<KeyArg, HashArg, KeyTraitsArg> HashSetType;
232
233     static void encode(ArgumentEncoder& encoder, const HashSetType& hashSet)
234     {
235         encoder << static_cast<uint64_t>(hashSet.size());
236         for (typename HashSetType::const_iterator it = hashSet.begin(), end = hashSet.end(); it != end; ++it)
237             encoder << *it;
238     }
239
240     static bool decode(ArgumentDecoder& decoder, HashSetType& hashSet)
241     {
242         uint64_t hashSetSize;
243         if (!decoder.decode(hashSetSize))
244             return false;
245
246         HashSetType tempHashSet;
247         for (uint64_t i = 0; i < hashSetSize; ++i) {
248             KeyArg key;
249             if (!decoder.decode(key))
250                 return false;
251
252             if (!tempHashSet.add(key).isNewEntry) {
253                 // The hash map already has the specified key, bail.
254                 decoder.markInvalid();
255                 return false;
256             }
257         }
258
259         hashSet.swap(tempHashSet);
260         return true;
261     }
262 };
263
264 template<> struct ArgumentCoder<AtomicString> {
265     static void encode(ArgumentEncoder&, const AtomicString&);
266     static bool decode(ArgumentDecoder&, AtomicString&);
267 };
268
269 template<> struct ArgumentCoder<CString> {
270     static void encode(ArgumentEncoder&, const CString&);
271     static bool decode(ArgumentDecoder&, CString&);
272 };
273
274 template<> struct ArgumentCoder<String> {
275     static void encode(ArgumentEncoder&, const String&);
276     static bool decode(ArgumentDecoder&, String&);
277 };
278
279 } // namespace IPC
280
281 #endif // ArgumentCoders_h