Home | History | Annotate | Download | only in CoreIPC
      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