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