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
38namespace IPC {
39
40// An argument coder works on POD types
41template<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
53template<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
85template<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
107template<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
129template<bool fixedSizeElements, typename T, size_t inlineCapacity> struct VectorArgumentCoder;
130
131template<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
160template<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
191template<typename T, size_t inlineCapacity> struct ArgumentCoder<Vector<T, inlineCapacity>> : VectorArgumentCoder<std::is_arithmetic<T>::value, T, inlineCapacity> { };
192
193template<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
230template<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
264template<> struct ArgumentCoder<AtomicString> {
265    static void encode(ArgumentEncoder&, const AtomicString&);
266    static bool decode(ArgumentDecoder&, AtomicString&);
267};
268
269template<> struct ArgumentCoder<CString> {
270    static void encode(ArgumentEncoder&, const CString&);
271    static bool decode(ArgumentDecoder&, CString&);
272};
273
274template<> 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
282