| OLD | NEW |
| (Empty) |
| 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_ARRAY_INTERNAL_H_ | |
| 6 #define MOJO_PUBLIC_BINDINGS_LIB_ARRAY_INTERNAL_H_ | |
| 7 | |
| 8 #include <new> | |
| 9 | |
| 10 #include "mojo/public/bindings/lib/bindings_internal.h" | |
| 11 #include "mojo/public/bindings/lib/bindings_serialization.h" | |
| 12 #include "mojo/public/cpp/bindings/buffer.h" | |
| 13 #include "mojo/public/cpp/bindings/passable.h" | |
| 14 #include "mojo/public/cpp/system/core.h" | |
| 15 | |
| 16 namespace mojo { | |
| 17 template <typename T> class Array; | |
| 18 | |
| 19 namespace internal { | |
| 20 | |
| 21 template <typename T> | |
| 22 struct ArrayDataTraits { | |
| 23 typedef T StorageType; | |
| 24 typedef Array<T> Wrapper; | |
| 25 typedef T& Ref; | |
| 26 typedef T const& ConstRef; | |
| 27 | |
| 28 static size_t GetStorageSize(size_t num_elements) { | |
| 29 return sizeof(StorageType) * num_elements; | |
| 30 } | |
| 31 static Ref ToRef(StorageType* storage, size_t offset) { | |
| 32 return storage[offset]; | |
| 33 } | |
| 34 static ConstRef ToConstRef(const StorageType* storage, size_t offset) { | |
| 35 return storage[offset]; | |
| 36 } | |
| 37 }; | |
| 38 | |
| 39 template <typename P> | |
| 40 struct ArrayDataTraits<P*> { | |
| 41 typedef StructPointer<P> StorageType; | |
| 42 typedef Array<typename P::Wrapper> Wrapper; | |
| 43 typedef P*& Ref; | |
| 44 typedef P* const& ConstRef; | |
| 45 | |
| 46 static size_t GetStorageSize(size_t num_elements) { | |
| 47 return sizeof(StorageType) * num_elements; | |
| 48 } | |
| 49 static Ref ToRef(StorageType* storage, size_t offset) { | |
| 50 return storage[offset].ptr; | |
| 51 } | |
| 52 static ConstRef ToConstRef(const StorageType* storage, size_t offset) { | |
| 53 return storage[offset].ptr; | |
| 54 } | |
| 55 }; | |
| 56 | |
| 57 // Specialization of Arrays for bools, optimized for space. It has the | |
| 58 // following differences from a generalized Array: | |
| 59 // * Each element takes up a single bit of memory. | |
| 60 // * Accessing a non-const single element uses a helper class |BitRef|, which | |
| 61 // emulates a reference to a bool. | |
| 62 template <> | |
| 63 struct ArrayDataTraits<bool> { | |
| 64 // Helper class to emulate a reference to a bool, used for direct element | |
| 65 // access. | |
| 66 class BitRef { | |
| 67 public: | |
| 68 ~BitRef(); | |
| 69 BitRef& operator=(bool value); | |
| 70 BitRef& operator=(const BitRef& value); | |
| 71 operator bool() const; | |
| 72 private: | |
| 73 friend struct ArrayDataTraits<bool>; | |
| 74 BitRef(uint8_t* storage, uint8_t mask); | |
| 75 BitRef(); | |
| 76 uint8_t* storage_; | |
| 77 uint8_t mask_; | |
| 78 }; | |
| 79 | |
| 80 typedef uint8_t StorageType; | |
| 81 typedef Array<bool> Wrapper; | |
| 82 typedef BitRef Ref; | |
| 83 typedef bool ConstRef; | |
| 84 | |
| 85 static size_t GetStorageSize(size_t num_elements) { | |
| 86 return ((num_elements + 7) / 8); | |
| 87 } | |
| 88 static BitRef ToRef(StorageType* storage, size_t offset) { | |
| 89 return BitRef(&storage[offset / 8], 1 << (offset % 8)); | |
| 90 } | |
| 91 static bool ToConstRef(const StorageType* storage, size_t offset) { | |
| 92 return (storage[offset / 8] & (1 << (offset % 8))) != 0; | |
| 93 } | |
| 94 }; | |
| 95 | |
| 96 // What follows is code to support the serialization of Array_Data<T>. There | |
| 97 // are two interesting cases: arrays of primitives and arrays of objects. | |
| 98 // Arrays of objects are represented as arrays of pointers to objects. | |
| 99 | |
| 100 template <typename T> | |
| 101 struct ArraySerializationHelper { | |
| 102 typedef T ElementType; | |
| 103 | |
| 104 static size_t ComputeSizeOfElements(const ArrayHeader* header, | |
| 105 const ElementType* elements) { | |
| 106 return 0; | |
| 107 } | |
| 108 | |
| 109 static void CloneElements(const ArrayHeader* header, | |
| 110 ElementType* elements, | |
| 111 Buffer* buf) { | |
| 112 } | |
| 113 | |
| 114 static void EncodePointersAndHandles(const ArrayHeader* header, | |
| 115 ElementType* elements, | |
| 116 std::vector<Handle>* handles) { | |
| 117 } | |
| 118 | |
| 119 static bool DecodePointersAndHandles(const ArrayHeader* header, | |
| 120 ElementType* elements, | |
| 121 Message* message) { | |
| 122 return true; | |
| 123 } | |
| 124 }; | |
| 125 | |
| 126 template <> | |
| 127 struct ArraySerializationHelper<Handle> { | |
| 128 typedef Handle ElementType; | |
| 129 | |
| 130 static size_t ComputeSizeOfElements(const ArrayHeader* header, | |
| 131 const ElementType* elements) { | |
| 132 return 0; | |
| 133 } | |
| 134 | |
| 135 static void CloneElements(const ArrayHeader* header, | |
| 136 ElementType* elements, | |
| 137 Buffer* buf) { | |
| 138 } | |
| 139 | |
| 140 static void EncodePointersAndHandles(const ArrayHeader* header, | |
| 141 ElementType* elements, | |
| 142 std::vector<Handle>* handles); | |
| 143 | |
| 144 static bool DecodePointersAndHandles(const ArrayHeader* header, | |
| 145 ElementType* elements, | |
| 146 Message* message); | |
| 147 }; | |
| 148 | |
| 149 template <typename P> | |
| 150 struct ArraySerializationHelper<P*> { | |
| 151 typedef StructPointer<P> ElementType; | |
| 152 | |
| 153 static size_t ComputeSizeOfElements(const ArrayHeader* header, | |
| 154 const ElementType* elements) { | |
| 155 size_t result = 0; | |
| 156 for (uint32_t i = 0; i < header->num_elements; ++i) { | |
| 157 if (elements[i].ptr) | |
| 158 result += elements[i].ptr->ComputeSize(); | |
| 159 } | |
| 160 return result; | |
| 161 } | |
| 162 | |
| 163 static void CloneElements(const ArrayHeader* header, | |
| 164 ElementType* elements, | |
| 165 Buffer* buf) { | |
| 166 for (uint32_t i = 0; i < header->num_elements; ++i) { | |
| 167 if (elements[i].ptr) | |
| 168 elements[i].ptr = elements[i].ptr->Clone(buf); | |
| 169 } | |
| 170 } | |
| 171 | |
| 172 static void EncodePointersAndHandles(const ArrayHeader* header, | |
| 173 ElementType* elements, | |
| 174 std::vector<Handle>* handles) { | |
| 175 for (uint32_t i = 0; i < header->num_elements; ++i) | |
| 176 Encode(&elements[i], handles); | |
| 177 } | |
| 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 Array_Data { | |
| 192 public: | |
| 193 typedef ArrayDataTraits<T> Traits; | |
| 194 typedef typename Traits::StorageType StorageType; | |
| 195 typedef typename Traits::Wrapper Wrapper; | |
| 196 typedef typename Traits::Ref Ref; | |
| 197 typedef typename Traits::ConstRef ConstRef; | |
| 198 | |
| 199 static Array_Data<T>* New(size_t num_elements, Buffer* buf) { | |
| 200 size_t num_bytes = sizeof(Array_Data<T>) + | |
| 201 Traits::GetStorageSize(num_elements); | |
| 202 return new (buf->Allocate(num_bytes)) Array_Data<T>(num_bytes, | |
| 203 num_elements); | |
| 204 } | |
| 205 | |
| 206 size_t size() const { return header_.num_elements; } | |
| 207 | |
| 208 Ref at(size_t offset) { | |
| 209 assert(offset < static_cast<size_t>(header_.num_elements)); | |
| 210 return Traits::ToRef(storage(), offset); | |
| 211 } | |
| 212 | |
| 213 ConstRef at(size_t offset) const { | |
| 214 assert(offset < static_cast<size_t>(header_.num_elements)); | |
| 215 return Traits::ToConstRef(storage(), offset); | |
| 216 } | |
| 217 | |
| 218 StorageType* storage() { | |
| 219 return reinterpret_cast<StorageType*>( | |
| 220 reinterpret_cast<char*>(this) + sizeof(*this)); | |
| 221 } | |
| 222 | |
| 223 const StorageType* storage() const { | |
| 224 return reinterpret_cast<const StorageType*>( | |
| 225 reinterpret_cast<const char*>(this) + sizeof(*this)); | |
| 226 } | |
| 227 | |
| 228 size_t ComputeSize() const { | |
| 229 return Align(header_.num_bytes) + | |
| 230 ArraySerializationHelper<T>::ComputeSizeOfElements(&header_, storage()); | |
| 231 } | |
| 232 | |
| 233 Array_Data<T>* Clone(Buffer* buf) const { | |
| 234 Array_Data<T>* clone = New(header_.num_elements, buf); | |
| 235 memcpy(clone->storage(), | |
| 236 storage(), | |
| 237 header_.num_bytes - sizeof(Array_Data<T>)); | |
| 238 | |
| 239 ArraySerializationHelper<T>::CloneElements(&clone->header_, | |
| 240 clone->storage(), buf); | |
| 241 return clone; | |
| 242 } | |
| 243 | |
| 244 void CloseHandles() { | |
| 245 // TODO(darin): Implement! | |
| 246 } | |
| 247 | |
| 248 void EncodePointersAndHandles(std::vector<Handle>* handles) { | |
| 249 ArraySerializationHelper<T>::EncodePointersAndHandles(&header_, storage(), | |
| 250 handles); | |
| 251 } | |
| 252 | |
| 253 bool DecodePointersAndHandles(Message* message) { | |
| 254 return ArraySerializationHelper<T>::DecodePointersAndHandles(&header_, | |
| 255 storage(), | |
| 256 message); | |
| 257 } | |
| 258 | |
| 259 private: | |
| 260 Array_Data(size_t num_bytes, size_t num_elements) { | |
| 261 header_.num_bytes = static_cast<uint32_t>(num_bytes); | |
| 262 header_.num_elements = static_cast<uint32_t>(num_elements); | |
| 263 } | |
| 264 ~Array_Data() {} | |
| 265 | |
| 266 internal::ArrayHeader header_; | |
| 267 | |
| 268 // Elements of type internal::ArrayDataTraits<T>::StorageType follow. | |
| 269 }; | |
| 270 MOJO_COMPILE_ASSERT(sizeof(Array_Data<char>) == 8, bad_sizeof_Array_Data); | |
| 271 | |
| 272 // UTF-8 encoded | |
| 273 typedef Array_Data<char> String_Data; | |
| 274 | |
| 275 template <typename T, bool kIsObject> struct ArrayTraits {}; | |
| 276 | |
| 277 template <typename T> struct ArrayTraits<T, true> { | |
| 278 typedef Array_Data<typename T::Data*> DataType; | |
| 279 typedef const T& ConstRef; | |
| 280 typedef T& Ref; | |
| 281 static typename T::Data* ToArrayElement(const T& value) { | |
| 282 return Unwrap(value); | |
| 283 } | |
| 284 // Something sketchy is indeed happening here... | |
| 285 static Ref ToRef(typename T::Data*& data) { | |
| 286 return *reinterpret_cast<T*>(&data); | |
| 287 } | |
| 288 static ConstRef ToConstRef(typename T::Data* const& data) { | |
| 289 return *reinterpret_cast<const T*>(&data); | |
| 290 } | |
| 291 }; | |
| 292 | |
| 293 template <typename T> struct ArrayTraits<T, false> { | |
| 294 typedef Array_Data<T> DataType; | |
| 295 typedef const T& ConstRef; | |
| 296 typedef T& Ref; | |
| 297 static T ToArrayElement(const T& value) { | |
| 298 return value; | |
| 299 } | |
| 300 static Ref ToRef(T& data) { return data; } | |
| 301 static ConstRef ToConstRef(const T& data) { return data; } | |
| 302 }; | |
| 303 | |
| 304 template <> struct ArrayTraits<bool, false> { | |
| 305 typedef Array_Data<bool> DataType; | |
| 306 typedef bool ConstRef; | |
| 307 typedef ArrayDataTraits<bool>::Ref Ref; | |
| 308 static bool ToArrayElement(const bool& value) { | |
| 309 return value; | |
| 310 } | |
| 311 static Ref ToRef(const Ref& data) { return data; } | |
| 312 static ConstRef ToConstRef(ConstRef data) { return data; } | |
| 313 }; | |
| 314 | |
| 315 template <> struct ArrayTraits<Handle, false> { | |
| 316 typedef Array_Data<Handle> DataType; | |
| 317 typedef Passable<Handle> ConstRef; | |
| 318 typedef AssignableAndPassable<Handle> Ref; | |
| 319 static Handle ToArrayElement(const Handle& value) { | |
| 320 return value; | |
| 321 } | |
| 322 static Ref ToRef(Handle& data) { return Ref(&data); } | |
| 323 static ConstRef ToConstRef(const Handle& data) { | |
| 324 return ConstRef(const_cast<Handle*>(&data)); | |
| 325 } | |
| 326 }; | |
| 327 | |
| 328 template <> struct ArrayTraits<DataPipeConsumerHandle, false> { | |
| 329 typedef Array_Data<DataPipeConsumerHandle> DataType; | |
| 330 typedef Passable<DataPipeConsumerHandle> ConstRef; | |
| 331 typedef AssignableAndPassable<DataPipeConsumerHandle> Ref; | |
| 332 static DataPipeConsumerHandle ToArrayElement( | |
| 333 const DataPipeConsumerHandle& value) { | |
| 334 return value; | |
| 335 } | |
| 336 static Ref ToRef(DataPipeConsumerHandle& data) { return Ref(&data); } | |
| 337 static ConstRef ToConstRef(const DataPipeConsumerHandle& data) { | |
| 338 return ConstRef(const_cast<DataPipeConsumerHandle*>(&data)); | |
| 339 } | |
| 340 }; | |
| 341 | |
| 342 template <> struct ArrayTraits<DataPipeProducerHandle, false> { | |
| 343 typedef Array_Data<DataPipeProducerHandle> DataType; | |
| 344 typedef Passable<DataPipeProducerHandle> ConstRef; | |
| 345 typedef AssignableAndPassable<DataPipeProducerHandle> Ref; | |
| 346 static DataPipeProducerHandle ToArrayElement( | |
| 347 const DataPipeProducerHandle& value) { | |
| 348 return value; | |
| 349 } | |
| 350 static Ref ToRef(DataPipeProducerHandle& data) { return Ref(&data); } | |
| 351 static ConstRef ToConstRef(const DataPipeProducerHandle& data) { | |
| 352 return ConstRef(const_cast<DataPipeProducerHandle*>(&data)); | |
| 353 } | |
| 354 }; | |
| 355 | |
| 356 template <> struct ArrayTraits<MessagePipeHandle, false> { | |
| 357 typedef Array_Data<MessagePipeHandle> DataType; | |
| 358 typedef Passable<MessagePipeHandle> ConstRef; | |
| 359 typedef AssignableAndPassable<MessagePipeHandle> Ref; | |
| 360 static MessagePipeHandle ToArrayElement(const MessagePipeHandle& value) { | |
| 361 return value; | |
| 362 } | |
| 363 static Ref ToRef(MessagePipeHandle& data) { return Ref(&data); } | |
| 364 static ConstRef ToConstRef(const MessagePipeHandle& data) { | |
| 365 return ConstRef(const_cast<MessagePipeHandle*>(&data)); | |
| 366 } | |
| 367 }; | |
| 368 | |
| 369 } // namespace internal | |
| 370 } // namespace mojo | |
| 371 | |
| 372 #endif // MOJO_PUBLIC_BINDINGS_LIB_ARRAY_INTERNAL_H_ | |
| OLD | NEW |