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