• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/HashMap.h>
33 #include <wtf/TypeTraits.h>
34 #include <wtf/Vector.h>
35 #include <wtf/text/AtomicString.h>
36 #include <wtf/text/CString.h>
37 #include <wtf/text/WTFString.h>
38 
39 namespace CoreIPC {
40 
41 // An argument coder works on POD types
42 template<typename T> struct SimpleArgumentCoder {
encodeSimpleArgumentCoder43     static void encode(ArgumentEncoder* encoder, const T& t)
44     {
45         encoder->encodeBytes(reinterpret_cast<const uint8_t*>(&t), sizeof(T));
46     }
decodeSimpleArgumentCoder47     static bool decode(ArgumentDecoder* decoder, T& t)
48     {
49         return decoder->decodeBytes(reinterpret_cast<uint8_t*>(&t), sizeof(T));
50     }
51 };
52 
53 template<typename T, typename U> struct ArgumentCoder<std::pair<T, U> > {
54     static void encode(ArgumentEncoder* encoder, const std::pair<T, U>& pair)
55     {
56         encoder->encode(pair.first);
57         encoder->encode(pair.second);
58     }
59 
60     static bool decode(ArgumentDecoder* decoder, std::pair<T, U>& pair)
61     {
62         T first;
63         if (!decoder->decode(first))
64             return false;
65 
66         U second;
67         if (!decoder->decode(second))
68             return false;
69 
70         pair.first = first;
71         pair.second = second;
72         return true;
73     }
74 };
75 
76 template<bool fixedSizeElements, typename T> struct VectorArgumentCoder;
77 
78 template<typename T> struct VectorArgumentCoder<false, T> {
79     static void encode(ArgumentEncoder* encoder, const Vector<T>& vector)
80     {
81         encoder->encodeUInt64(vector.size());
82         for (size_t i = 0; i < vector.size(); ++i)
83             encoder->encode(vector[i]);
84     }
85 
86     static bool decode(ArgumentDecoder* decoder, Vector<T>& vector)
87     {
88         uint64_t size;
89         if (!decoder->decodeUInt64(size))
90             return false;
91 
92         Vector<T> tmp;
93         for (size_t i = 0; i < size; ++i) {
94             T element;
95             if (!decoder->decode(element))
96                 return false;
97 
98             tmp.append(element);
99         }
100 
101         tmp.shrinkToFit();
102         vector.swap(tmp);
103         return true;
104     }
105 };
106 
107 template<typename T> struct VectorArgumentCoder<true, T> {
108     static void encode(ArgumentEncoder* encoder, const Vector<T>& vector)
109     {
110         encoder->encodeUInt64(vector.size());
111         // FIXME: If we could tell the encoder to align the buffer, we could just do an encodeBytes here.
112         for (size_t i = 0; i < vector.size(); ++i)
113             encoder->encode(vector[i]);
114     }
115 
116     static bool decode(ArgumentDecoder* decoder, Vector<T>& vector)
117     {
118         uint64_t size;
119         if (!decoder->decodeUInt64(size))
120             return false;
121 
122         // Since we know the total size of the elements, we can allocate the vector in
123         // one fell swoop. Before allocating we must however make sure that the decoder buffer
124         // is big enough.
125         if (!decoder->bufferIsLargeEnoughToContain<T>(size)) {
126             decoder->markInvalid();
127             return false;
128         }
129 
130         Vector<T> tmp;
131         tmp.reserveCapacity(size);
132 
133         for (size_t i = 0; i < size; ++i) {
134             T element;
135             if (!decoder->decode(element))
136                 return false;
137 
138             tmp.uncheckedAppend(element);
139         }
140 
141         vector.swap(tmp);
142         return true;
143     }
144 };
145 
146 template<typename T> struct ArgumentCoder<Vector<T> > : VectorArgumentCoder<WTF::IsArithmetic<T>::value, T> { };
147 
148 // Specialization for Vector<uint8_t>
149 template<> struct ArgumentCoder<Vector<uint8_t> > {
150     static void encode(ArgumentEncoder* encoder, const Vector<uint8_t>& vector)
151     {
152         encoder->encodeBytes(vector.data(), vector.size());
153     }
154 
155     static bool decode(ArgumentDecoder* decoder, Vector<uint8_t>& vector)
156     {
157         return decoder->decodeBytes(vector);
158     }
159 };
160 
161 template<typename KeyArg, typename MappedArg, typename HashArg, typename KeyTraitsArg, typename MappedTraitsArg> struct ArgumentCoder<HashMap<KeyArg, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg> > {
162     typedef HashMap<KeyArg, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg> HashMapType;
163 
164     static void encode(ArgumentEncoder* encoder, const HashMapType& hashMap)
165     {
166         encoder->encodeUInt64(hashMap.size());
167         for (typename HashMapType::const_iterator it = hashMap.begin(), end = hashMap.end(); it != end; ++it)
168             encoder->encode(*it);
169     }
170 
171     static bool decode(ArgumentDecoder* decoder, HashMapType& hashMap)
172     {
173         uint64_t hashMapSize;
174         if (!decoder->decode(hashMapSize))
175             return false;
176 
177         HashMapType tempHashMap;
178         for (uint64_t i = 0; i < hashMapSize; ++i) {
179             KeyArg key;
180             MappedArg value;
181             if (!decoder->decode(key))
182                 return false;
183             if (!decoder->decode(value))
184                 return false;
185 
186             if (!tempHashMap.add(key, value).second) {
187                 // The hash map already has the specified key, bail.
188                 decoder->markInvalid();
189                 return false;
190             }
191         }
192 
193         hashMap.swap(tempHashMap);
194         return true;
195     }
196 };
197 
198 template<> struct ArgumentCoder<CString> {
199     static void encode(ArgumentEncoder* encoder, const CString& string)
200     {
201         // Special case the null string.
202         if (string.isNull()) {
203             encoder->encodeUInt32(std::numeric_limits<uint32_t>::max());
204             return;
205         }
206 
207         uint32_t length = string.length();
208         encoder->encode(length);
209         encoder->encodeBytes(reinterpret_cast<const uint8_t*>(string.data()), length);
210     }
211 
212     static bool decode(ArgumentDecoder* decoder, CString& result)
213     {
214         uint32_t length;
215         if (!decoder->decode(length))
216             return false;
217 
218         if (length == std::numeric_limits<uint32_t>::max()) {
219             // This is the null string.
220             result = CString();
221             return true;
222         }
223 
224         // Before allocating the string, make sure that the decoder buffer is big enough.
225         if (!decoder->bufferIsLargeEnoughToContain<char>(length)) {
226             decoder->markInvalid();
227             return false;
228         }
229 
230         char* buffer;
231         CString string = CString::newUninitialized(length, buffer);
232         if (!decoder->decodeBytes(reinterpret_cast<uint8_t*>(buffer), length))
233             return false;
234 
235         result = string;
236         return true;
237     }
238 };
239 
240 template<> struct ArgumentCoder<String> {
241     static void encode(ArgumentEncoder* encoder, const String& string)
242     {
243         // Special case the null string.
244         if (string.isNull()) {
245             encoder->encodeUInt32(std::numeric_limits<uint32_t>::max());
246             return;
247         }
248 
249         uint32_t length = string.length();
250         encoder->encode(length);
251         encoder->encodeBytes(reinterpret_cast<const uint8_t*>(string.characters()), length * sizeof(UChar));
252     }
253 
254     static bool decode(ArgumentDecoder* decoder, String& result)
255     {
256         uint32_t length;
257         if (!decoder->decode(length))
258             return false;
259 
260         if (length == std::numeric_limits<uint32_t>::max()) {
261             // This is the null string.
262             result = String();
263             return true;
264         }
265 
266         // Before allocating the string, make sure that the decoder buffer is big enough.
267         if (!decoder->bufferIsLargeEnoughToContain<UChar>(length)) {
268             decoder->markInvalid();
269             return false;
270         }
271 
272         UChar* buffer;
273         String string = String::createUninitialized(length, buffer);
274         if (!decoder->decodeBytes(reinterpret_cast<uint8_t*>(buffer), length * sizeof(UChar)))
275             return false;
276 
277         result = string;
278         return true;
279     }
280 };
281 
282 template<> struct ArgumentCoder<AtomicString> {
283     static void encode(ArgumentEncoder* encoder, const AtomicString& atomicString)
284     {
285         encoder->encode(atomicString.string());
286     }
287 
288     static bool decode(ArgumentDecoder* decoder, AtomicString& atomicString)
289     {
290         String string;
291         if (!decoder->decode(string))
292             return false;
293 
294         atomicString = string;
295         return true;
296     }
297 };
298 
299 } // namespace CoreIPC
300 
301 #endif // SimpleArgumentCoder_h
302