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