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 |