2011-06-14 Anders Carlsson <andersca@apple.com>
[WebKit-https.git] / Source / WebKit2 / Platform / CoreIPC / 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/TypeTraits.h>
35 #include <wtf/Vector.h>
36
37 namespace CoreIPC {
38
39 // An argument coder works on POD types
40 template<typename T> struct SimpleArgumentCoder {
41     static void encode(ArgumentEncoder* encoder, const T& t)
42     {
43         encoder->encodeBytes(reinterpret_cast<const uint8_t*>(&t), sizeof(T));
44     }
45     static bool decode(ArgumentDecoder* decoder, T& t)
46     {
47         return decoder->decodeBytes(reinterpret_cast<uint8_t*>(&t), sizeof(T));
48     }
49 };
50
51 template<typename T, typename U> struct ArgumentCoder<std::pair<T, U> > {
52     static void encode(ArgumentEncoder* encoder, const std::pair<T, U>& pair)
53     {
54         encoder->encode(pair.first);
55         encoder->encode(pair.second);
56     }
57
58     static bool decode(ArgumentDecoder* decoder, std::pair<T, U>& pair)
59     {
60         T first;
61         if (!decoder->decode(first))
62             return false;
63
64         U second;
65         if (!decoder->decode(second))
66             return false;
67
68         pair.first = first;
69         pair.second = second;
70         return true;
71     }
72 };
73
74 template<bool fixedSizeElements, typename T> struct VectorArgumentCoder;
75
76 template<typename T> struct VectorArgumentCoder<false, T> {
77     static void encode(ArgumentEncoder* encoder, const Vector<T>& vector)
78     {
79         encoder->encodeUInt64(vector.size());
80         for (size_t i = 0; i < vector.size(); ++i)
81             encoder->encode(vector[i]);
82     }
83
84     static bool decode(ArgumentDecoder* decoder, Vector<T>& vector)
85     {
86         uint64_t size;
87         if (!decoder->decodeUInt64(size))
88             return false;
89
90         Vector<T> tmp;
91         for (size_t i = 0; i < size; ++i) {
92             T element;
93             if (!decoder->decode(element))
94                 return false;
95             
96             tmp.append(element);
97         }
98
99         tmp.shrinkToFit();
100         vector.swap(tmp);
101         return true;
102     }
103 };
104
105 template<typename T> struct VectorArgumentCoder<true, T> {
106     static void encode(ArgumentEncoder* encoder, const Vector<T>& vector)
107     {
108         encoder->encodeUInt64(vector.size());
109         // FIXME: If we could tell the encoder to align the buffer, we could just do an encodeBytes here.
110         for (size_t i = 0; i < vector.size(); ++i)
111             encoder->encode(vector[i]);
112     }
113     
114     static bool decode(ArgumentDecoder* decoder, Vector<T>& vector)
115     {
116         uint64_t size;
117         if (!decoder->decodeUInt64(size))
118             return false;
119
120         // Since we know the total size of the elements, we can allocate the vector in
121         // one fell swoop. Before allocating we must however make sure that the decoder buffer
122         // is big enough.
123         if (!decoder->bufferIsLargeEnoughToContain<T>(size)) {
124             decoder->markInvalid();
125             return false;
126         }
127
128         Vector<T> tmp;
129         tmp.reserveCapacity(size);
130
131         for (size_t i = 0; i < size; ++i) {
132             T element;
133             if (!decoder->decode(element))
134                 return false;
135             
136             tmp.uncheckedAppend(element);
137         }
138
139         vector.swap(tmp);
140         return true;
141     }
142 };
143
144 template<typename T> struct ArgumentCoder<Vector<T> > : VectorArgumentCoder<WTF::IsArithmetic<T>::value, T> { };
145
146 // Specialization for Vector<uint8_t>
147 template<> struct ArgumentCoder<Vector<uint8_t> > {
148     static void encode(ArgumentEncoder* encoder, const Vector<uint8_t>& vector)
149     {
150         encoder->encodeBytes(vector.data(), vector.size());
151     }
152
153     static bool decode(ArgumentDecoder* decoder, Vector<uint8_t>& vector)
154     {
155         return decoder->decodeBytes(vector);
156     }
157 };
158
159 template<typename KeyArg, typename MappedArg, typename HashArg, typename KeyTraitsArg, typename MappedTraitsArg> struct ArgumentCoder<HashMap<KeyArg, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg> > {
160     typedef HashMap<KeyArg, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg> HashMapType;
161
162     static void encode(ArgumentEncoder* encoder, const HashMapType& hashMap)
163     {
164         encoder->encodeUInt64(hashMap.size());
165         for (typename HashMapType::const_iterator it = hashMap.begin(), end = hashMap.end(); it != end; ++it)
166             encoder->encode(*it);
167     }
168
169     static bool decode(ArgumentDecoder* decoder, HashMapType& hashMap)
170     {
171         uint64_t hashMapSize;
172         if (!decoder->decode(hashMapSize))
173             return false;
174
175         HashMapType tempHashMap;
176         for (uint64_t i = 0; i < hashMapSize; ++i) {
177             KeyArg key;
178             MappedArg value;
179             if (!decoder->decode(key))
180                 return false;
181             if (!decoder->decode(value))
182                 return false;
183
184             if (!tempHashMap.add(key, value).second) {
185                 // The hash map already has the specified key, bail.
186                 decoder->markInvalid();
187                 return false;
188             }
189         }
190
191         hashMap.swap(tempHashMap);
192         return true;
193     }
194 };
195
196 template<> struct ArgumentCoder<AtomicString> {
197     static void encode(ArgumentEncoder*, const AtomicString&);
198     static bool decode(ArgumentDecoder*, AtomicString&);
199 };
200
201 template<> struct ArgumentCoder<CString> {
202     static void encode(ArgumentEncoder*, const CString&);
203     static bool decode(ArgumentDecoder*, CString&);
204 };
205
206 template<> struct ArgumentCoder<String> {
207     static void encode(ArgumentEncoder*, const String&);
208     static bool decode(ArgumentDecoder*, String&);
209 };
210
211 } // namespace CoreIPC
212
213 #endif // SimpleArgumentCoder_h