Home | History | Annotate | Download | only in lib
      1 // Copyright 2013 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #ifndef MOJO_PUBLIC_BINDINGS_LIB_BINDINGS_SERIALIZATION_H_
      6 #define MOJO_PUBLIC_BINDINGS_LIB_BINDINGS_SERIALIZATION_H_
      7 
      8 #include <string.h>
      9 
     10 #include <vector>
     11 
     12 #include "mojo/public/bindings/lib/bindings.h"
     13 #include "mojo/public/bindings/lib/message.h"
     14 
     15 namespace mojo {
     16 namespace internal {
     17 
     18 size_t Align(size_t size);
     19 
     20 // Pointers are encoded as relative offsets. The offsets are relative to the
     21 // address of where the offset value is stored, such that the pointer may be
     22 // recovered with the expression:
     23 //
     24 //   ptr = reinterpret_cast<char*>(offset) + *offset
     25 //
     26 // A null pointer is encoded as an offset value of 0.
     27 //
     28 void EncodePointer(const void* ptr, uint64_t* offset);
     29 const void* DecodePointerRaw(const uint64_t* offset);
     30 
     31 template <typename T>
     32 inline void DecodePointer(const uint64_t* offset, T** ptr) {
     33   *ptr = reinterpret_cast<T*>(const_cast<void*>(DecodePointerRaw(offset)));
     34 }
     35 
     36 // Check that the given pointer references memory contained within the message.
     37 bool ValidatePointer(const void* ptr, const Message& message);
     38 
     39 // Handles are encoded as indices into a vector of handles. These functions
     40 // manipulate the value of |handle|, mapping it to and from an index.
     41 void EncodeHandle(Handle* handle, std::vector<Handle>* handles);
     42 bool DecodeHandle(Handle* handle, std::vector<Handle>* handles);
     43 
     44 // All objects (structs and arrays) support the following operations:
     45 //  - computing size
     46 //  - cloning
     47 //  - encoding pointers and handles
     48 //  - decoding pointers and handles
     49 //
     50 // The following functions are used to select the proper ObjectTraits<>
     51 // specialization.
     52 
     53 template <typename T>
     54 inline size_t ComputeSizeOf(const T* obj) {
     55   return obj ? ObjectTraits<T>::ComputeSizeOf(obj) : 0;
     56 }
     57 
     58 template <typename T>
     59 inline T* Clone(const T* obj, Buffer* buf) {
     60   return obj ? ObjectTraits<T>::Clone(obj, buf) : NULL;
     61 }
     62 
     63 template <typename T>
     64 inline void CloseHandles(T* obj) {
     65   if (obj)
     66     ObjectTraits<T>::CloseHandles(obj);
     67 }
     68 
     69 template <typename T>
     70 inline void EncodePointersAndHandles(T* obj,
     71                                      std::vector<Handle>* handles) {
     72   ObjectTraits<T>::EncodePointersAndHandles(obj, handles);
     73 }
     74 
     75 template <typename T>
     76 inline bool DecodePointersAndHandles(T* obj, Message* message) {
     77   return ObjectTraits<T>::DecodePointersAndHandles(obj, message);
     78 }
     79 
     80 // The following 2 functions are used to encode/decode all objects (structs and
     81 // arrays) in a consistent manner.
     82 
     83 template <typename T>
     84 inline void Encode(T* obj, std::vector<Handle>* handles) {
     85   if (obj->ptr)
     86     EncodePointersAndHandles(obj->ptr, handles);
     87   EncodePointer(obj->ptr, &obj->offset);
     88 }
     89 
     90 template <typename T>
     91 inline bool Decode(T* obj, Message* message) {
     92   DecodePointer(&obj->offset, &obj->ptr);
     93   if (obj->ptr) {
     94     if (!ValidatePointer(obj->ptr, *message))
     95       return false;
     96     if (!DecodePointersAndHandles(obj->ptr, message))
     97       return false;
     98   }
     99   return true;
    100 }
    101 
    102 // What follows is code to support the ObjectTraits<> specialization of
    103 // Array_Data<T>. There are two interesting cases: arrays of primitives and
    104 // arrays of objects. Arrays of objects are represented as arrays of pointers
    105 // to objects.
    106 
    107 template <typename T>
    108 struct ArrayHelper {
    109   typedef T ElementType;
    110 
    111   static size_t ComputeSizeOfElements(const ArrayHeader* header,
    112                                       const ElementType* elements) {
    113     return 0;
    114   }
    115 
    116   static void CloneElements(const ArrayHeader* header,
    117                             ElementType* elements,
    118                             Buffer* buf) {
    119   }
    120 
    121   static void EncodePointersAndHandles(const ArrayHeader* header,
    122                                        ElementType* elements,
    123                                        std::vector<Handle>* handles) {
    124   }
    125   static bool DecodePointersAndHandles(const ArrayHeader* header,
    126                                        ElementType* elements,
    127                                        Message* message) {
    128     return true;
    129   }
    130 };
    131 
    132 template <>
    133 struct ArrayHelper<Handle> {
    134   typedef Handle ElementType;
    135 
    136   static size_t ComputeSizeOfElements(const ArrayHeader* header,
    137                                       const ElementType* elements) {
    138     return 0;
    139   }
    140 
    141   static void CloneElements(const ArrayHeader* header,
    142                             ElementType* elements,
    143                             Buffer* buf) {
    144   }
    145 
    146   static void EncodePointersAndHandles(const ArrayHeader* header,
    147                                        ElementType* elements,
    148                                        std::vector<Handle>* handles);
    149   static bool DecodePointersAndHandles(const ArrayHeader* header,
    150                                        ElementType* elements,
    151                                        Message* message);
    152 };
    153 
    154 template <typename P>
    155 struct ArrayHelper<P*> {
    156   typedef StructPointer<P> ElementType;
    157 
    158   static size_t ComputeSizeOfElements(const ArrayHeader* header,
    159                                       const ElementType* elements) {
    160     size_t result = 0;
    161     for (uint32_t i = 0; i < header->num_elements; ++i)
    162       result += ComputeSizeOf(elements[i].ptr);
    163     return result;
    164   }
    165 
    166   static void CloneElements(const ArrayHeader* header,
    167                             ElementType* elements,
    168                             Buffer* buf) {
    169     for (uint32_t i = 0; i < header->num_elements; ++i)
    170       elements[i].ptr = Clone(elements[i].ptr, buf);
    171   }
    172 
    173   static void EncodePointersAndHandles(const ArrayHeader* header,
    174                                        ElementType* elements,
    175                                        std::vector<Handle>* handles) {
    176     for (uint32_t i = 0; i < header->num_elements; ++i)
    177       Encode(&elements[i], handles);
    178   }
    179   static bool DecodePointersAndHandles(const ArrayHeader* header,
    180                                        ElementType* elements,
    181                                        Message* message) {
    182     for (uint32_t i = 0; i < header->num_elements; ++i) {
    183       if (!Decode(&elements[i], message))
    184         return false;
    185     }
    186     return true;
    187   }
    188 };
    189 
    190 template <typename T>
    191 class ObjectTraits<Array_Data<T> > {
    192  public:
    193   static size_t ComputeSizeOf(const Array_Data<T>* array) {
    194     return Align(array->header_.num_bytes) +
    195         ArrayHelper<T>::ComputeSizeOfElements(&array->header_,
    196                                               array->storage());
    197   }
    198 
    199   static Array_Data<T>* Clone(const Array_Data<T>* array, Buffer* buf) {
    200     Array_Data<T>* clone = Array_Data<T>::New(array->header_.num_elements, buf);
    201     memcpy(clone->storage(),
    202            array->storage(),
    203            array->header_.num_bytes - sizeof(Array_Data<T>));
    204 
    205     ArrayHelper<T>::CloneElements(&clone->header_, clone->storage(), buf);
    206     return clone;
    207   }
    208 
    209   static void CloseHandles(Array_Data<T>* array) {
    210     // TODO(darin): Implement!
    211   }
    212 
    213   static void EncodePointersAndHandles(Array_Data<T>* array,
    214                                        std::vector<Handle>* handles) {
    215     ArrayHelper<T>::EncodePointersAndHandles(&array->header_, array->storage(),
    216                                              handles);
    217   }
    218 
    219   static bool DecodePointersAndHandles(Array_Data<T>* array,
    220                                        Message* message) {
    221     return ArrayHelper<T>::DecodePointersAndHandles(&array->header_,
    222                                                     array->storage(),
    223                                                     message);
    224   }
    225 };
    226 
    227 }  // namespace internal
    228 }  // namespace mojo
    229 
    230 #endif  // MOJO_PUBLIC_BINDINGS_LIB_BINDINGS_SERIALIZATION_H_
    231