Upstream version 7.35.144.0
[platform/framework/web/crosswalk.git] / src / mojo / public / 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_BINDINGS_LIB_ARRAY_INTERNAL_H_
6 #define MOJO_PUBLIC_BINDINGS_LIB_ARRAY_INTERNAL_H_
7
8 #include <new>
9
10 #include "mojo/public/bindings/buffer.h"
11 #include "mojo/public/bindings/lib/bindings_internal.h"
12 #include "mojo/public/bindings/lib/bindings_serialization.h"
13 #include "mojo/public/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_