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 { 43 static void encode(ArgumentEncoder* encoder, const T& t) 44 { 45 encoder->encodeBytes(reinterpret_cast<const uint8_t*>(&t), sizeof(T)); 46 } 47 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