Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(337)

Side by Side Diff: mojo/public/cpp/bindings/lib/array_internal.h

Issue 294833002: Mojo: more idiomatic C++ bindings (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fix windows bustage Created 6 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_ARRAY_INTERNAL_H_ 5 #ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_ARRAY_INTERNAL_H_
6 #define MOJO_PUBLIC_CPP_BINDINGS_LIB_ARRAY_INTERNAL_H_ 6 #define MOJO_PUBLIC_CPP_BINDINGS_LIB_ARRAY_INTERNAL_H_
7 7
8 #include <new> 8 #include <new>
9 #include <vector>
9 10
10 #include "mojo/public/cpp/bindings/buffer.h"
11 #include "mojo/public/cpp/bindings/lib/bindings_internal.h" 11 #include "mojo/public/cpp/bindings/lib/bindings_internal.h"
12 #include "mojo/public/cpp/bindings/lib/bindings_serialization.h" 12 #include "mojo/public/cpp/bindings/lib/bindings_serialization.h"
13 #include "mojo/public/cpp/bindings/passable.h" 13 #include "mojo/public/cpp/bindings/lib/buffer.h"
14 14
15 namespace mojo { 15 namespace mojo {
16 template <typename T> class Array; 16 template <typename T> class Array;
17 class String;
17 18
18 namespace internal { 19 namespace internal {
19 20
20 template <typename T> 21 template <typename T>
21 struct ArrayDataTraits { 22 struct ArrayDataTraits {
22 typedef T StorageType; 23 typedef T StorageType;
23 typedef Array<T> Wrapper;
24 typedef T& Ref; 24 typedef T& Ref;
25 typedef T const& ConstRef; 25 typedef T const& ConstRef;
26 26
27 static size_t GetStorageSize(size_t num_elements) { 27 static size_t GetStorageSize(size_t num_elements) {
28 return sizeof(StorageType) * num_elements; 28 return sizeof(StorageType) * num_elements;
29 } 29 }
30 static Ref ToRef(StorageType* storage, size_t offset) { 30 static Ref ToRef(StorageType* storage, size_t offset) {
31 return storage[offset]; 31 return storage[offset];
32 } 32 }
33 static ConstRef ToConstRef(const StorageType* storage, size_t offset) { 33 static ConstRef ToConstRef(const StorageType* storage, size_t offset) {
34 return storage[offset]; 34 return storage[offset];
35 } 35 }
36 }; 36 };
37 37
38 template <typename P> 38 template <typename P>
39 struct ArrayDataTraits<P*> { 39 struct ArrayDataTraits<P*> {
40 typedef StructPointer<P> StorageType; 40 typedef StructPointer<P> StorageType;
41 typedef Array<typename P::Wrapper> Wrapper;
42 typedef P*& Ref; 41 typedef P*& Ref;
43 typedef P* const& ConstRef; 42 typedef P* const& ConstRef;
44 43
45 static size_t GetStorageSize(size_t num_elements) { 44 static size_t GetStorageSize(size_t num_elements) {
46 return sizeof(StorageType) * num_elements; 45 return sizeof(StorageType) * num_elements;
47 } 46 }
48 static Ref ToRef(StorageType* storage, size_t offset) { 47 static Ref ToRef(StorageType* storage, size_t offset) {
49 return storage[offset].ptr; 48 return storage[offset].ptr;
50 } 49 }
51 static ConstRef ToConstRef(const StorageType* storage, size_t offset) { 50 static ConstRef ToConstRef(const StorageType* storage, size_t offset) {
(...skipping 18 matching lines...) Expand all
70 operator bool() const; 69 operator bool() const;
71 private: 70 private:
72 friend struct ArrayDataTraits<bool>; 71 friend struct ArrayDataTraits<bool>;
73 BitRef(uint8_t* storage, uint8_t mask); 72 BitRef(uint8_t* storage, uint8_t mask);
74 BitRef(); 73 BitRef();
75 uint8_t* storage_; 74 uint8_t* storage_;
76 uint8_t mask_; 75 uint8_t mask_;
77 }; 76 };
78 77
79 typedef uint8_t StorageType; 78 typedef uint8_t StorageType;
80 typedef Array<bool> Wrapper;
81 typedef BitRef Ref; 79 typedef BitRef Ref;
82 typedef bool ConstRef; 80 typedef bool ConstRef;
83 81
84 static size_t GetStorageSize(size_t num_elements) { 82 static size_t GetStorageSize(size_t num_elements) {
85 return ((num_elements + 7) / 8); 83 return ((num_elements + 7) / 8);
86 } 84 }
87 static BitRef ToRef(StorageType* storage, size_t offset) { 85 static BitRef ToRef(StorageType* storage, size_t offset) {
88 return BitRef(&storage[offset / 8], 1 << (offset % 8)); 86 return BitRef(&storage[offset / 8], 1 << (offset % 8));
89 } 87 }
90 static bool ToConstRef(const StorageType* storage, size_t offset) { 88 static bool ToConstRef(const StorageType* storage, size_t offset) {
91 return (storage[offset / 8] & (1 << (offset % 8))) != 0; 89 return (storage[offset / 8] & (1 << (offset % 8))) != 0;
92 } 90 }
93 }; 91 };
94 92
95 // What follows is code to support the serialization of Array_Data<T>. There 93 // 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. 94 // are two interesting cases: arrays of primitives and arrays of objects.
97 // Arrays of objects are represented as arrays of pointers to objects. 95 // Arrays of objects are represented as arrays of pointers to objects.
98 96
99 template <typename T, bool kIsHandle> struct ArraySerializationHelper; 97 template <typename T, bool kIsHandle> struct ArraySerializationHelper;
100 98
101 template <typename T> 99 template <typename T>
102 struct ArraySerializationHelper<T, false> { 100 struct ArraySerializationHelper<T, false> {
103 typedef typename ArrayDataTraits<T>::StorageType ElementType; 101 typedef typename ArrayDataTraits<T>::StorageType ElementType;
104 102
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, 103 static void EncodePointersAndHandles(const ArrayHeader* header,
123 ElementType* elements, 104 ElementType* elements,
124 std::vector<Handle>* handles) { 105 std::vector<Handle>* handles) {
125 } 106 }
126 107
127 static bool DecodePointersAndHandles(const ArrayHeader* header, 108 static bool DecodePointersAndHandles(const ArrayHeader* header,
128 ElementType* elements, 109 ElementType* elements,
129 Message* message) { 110 Message* message) {
130 return true; 111 return true;
131 } 112 }
132 }; 113 };
133 114
134 template <> 115 template <>
135 struct ArraySerializationHelper<Handle, true> { 116 struct ArraySerializationHelper<Handle, true> {
136 typedef ArrayDataTraits<Handle>::StorageType ElementType; 117 typedef ArrayDataTraits<Handle>::StorageType ElementType;
137 118
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, 119 static void EncodePointersAndHandles(const ArrayHeader* header,
153 ElementType* elements, 120 ElementType* elements,
154 std::vector<Handle>* handles); 121 std::vector<Handle>* handles);
155 122
156 static bool DecodePointersAndHandles(const ArrayHeader* header, 123 static bool DecodePointersAndHandles(const ArrayHeader* header,
157 ElementType* elements, 124 ElementType* elements,
158 Message* message); 125 Message* message);
159 }; 126 };
160 127
161 template <typename H> 128 template <typename H>
162 struct ArraySerializationHelper<H, true> { 129 struct ArraySerializationHelper<H, true> {
163 typedef typename ArrayDataTraits<H>::StorageType ElementType; 130 typedef typename ArrayDataTraits<H>::StorageType ElementType;
164 131
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, 132 static void EncodePointersAndHandles(const ArrayHeader* header,
184 ElementType* elements, 133 ElementType* elements,
185 std::vector<Handle>* handles) { 134 std::vector<Handle>* handles) {
186 ArraySerializationHelper<Handle, true>::EncodePointersAndHandles( 135 ArraySerializationHelper<Handle, true>::EncodePointersAndHandles(
187 header, elements, handles); 136 header, elements, handles);
188 } 137 }
189 138
190 static bool DecodePointersAndHandles(const ArrayHeader* header, 139 static bool DecodePointersAndHandles(const ArrayHeader* header,
191 ElementType* elements, 140 ElementType* elements,
192 Message* message) { 141 Message* message) {
193 return ArraySerializationHelper<Handle, true>::DecodePointersAndHandles( 142 return ArraySerializationHelper<Handle, true>::DecodePointersAndHandles(
194 header, elements, message); 143 header, elements, message);
195 } 144 }
196 }; 145 };
197 146
198 template <typename P> 147 template <typename P>
199 struct ArraySerializationHelper<P*, false> { 148 struct ArraySerializationHelper<P*, false> {
200 typedef typename ArrayDataTraits<P*>::StorageType ElementType; 149 typedef typename ArrayDataTraits<P*>::StorageType ElementType;
201 150
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, 151 static void EncodePointersAndHandles(const ArrayHeader* header,
233 ElementType* elements, 152 ElementType* elements,
234 std::vector<Handle>* handles) { 153 std::vector<Handle>* handles) {
235 for (uint32_t i = 0; i < header->num_elements; ++i) 154 for (uint32_t i = 0; i < header->num_elements; ++i)
236 Encode(&elements[i], handles); 155 Encode(&elements[i], handles);
237 } 156 }
238 157
239 static bool DecodePointersAndHandles(const ArrayHeader* header, 158 static bool DecodePointersAndHandles(const ArrayHeader* header,
240 ElementType* elements, 159 ElementType* elements,
241 Message* message) { 160 Message* message) {
242 for (uint32_t i = 0; i < header->num_elements; ++i) { 161 for (uint32_t i = 0; i < header->num_elements; ++i) {
243 if (!Decode(&elements[i], message)) 162 if (!Decode(&elements[i], message))
244 return false; 163 return false;
245 } 164 }
246 return true; 165 return true;
247 } 166 }
248 }; 167 };
249 168
250 template <typename T> 169 template <typename T>
251 class Array_Data { 170 class Array_Data {
252 public: 171 public:
253 typedef ArrayDataTraits<T> Traits; 172 typedef ArrayDataTraits<T> Traits;
254 typedef typename Traits::StorageType StorageType; 173 typedef typename Traits::StorageType StorageType;
255 typedef typename Traits::Wrapper Wrapper;
256 typedef typename Traits::Ref Ref; 174 typedef typename Traits::Ref Ref;
257 typedef typename Traits::ConstRef ConstRef; 175 typedef typename Traits::ConstRef ConstRef;
258 typedef ArraySerializationHelper<T, TypeTraits<T>::kIsHandle> Helper; 176 typedef ArraySerializationHelper<T, IsHandle<T>::value> Helper;
259 177
260 static Array_Data<T>* New(size_t num_elements, Buffer* buf, 178 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>) + 179 size_t num_bytes = sizeof(Array_Data<T>) +
263 Traits::GetStorageSize(num_elements); 180 Traits::GetStorageSize(num_elements);
264 return new (buf->Allocate(num_bytes, dtor)) Array_Data<T>(num_bytes, 181 return new (buf->Allocate(num_bytes)) Array_Data<T>(num_bytes,
265 num_elements); 182 num_elements);
266 }
267
268 static void Destructor(void* address) {
269 static_cast<Array_Data*>(address)->CloseHandles();
270 } 183 }
271 184
272 size_t size() const { return header_.num_elements; } 185 size_t size() const { return header_.num_elements; }
273 186
274 Ref at(size_t offset) { 187 Ref at(size_t offset) {
275 assert(offset < static_cast<size_t>(header_.num_elements)); 188 assert(offset < static_cast<size_t>(header_.num_elements));
276 return Traits::ToRef(storage(), offset); 189 return Traits::ToRef(storage(), offset);
277 } 190 }
278 191
279 ConstRef at(size_t offset) const { 192 ConstRef at(size_t offset) const {
280 assert(offset < static_cast<size_t>(header_.num_elements)); 193 assert(offset < static_cast<size_t>(header_.num_elements));
281 return Traits::ToConstRef(storage(), offset); 194 return Traits::ToConstRef(storage(), offset);
282 } 195 }
283 196
284 StorageType* storage() { 197 StorageType* storage() {
285 return reinterpret_cast<StorageType*>( 198 return reinterpret_cast<StorageType*>(
286 reinterpret_cast<char*>(this) + sizeof(*this)); 199 reinterpret_cast<char*>(this) + sizeof(*this));
287 } 200 }
288 201
289 const StorageType* storage() const { 202 const StorageType* storage() const {
290 return reinterpret_cast<const StorageType*>( 203 return reinterpret_cast<const StorageType*>(
291 reinterpret_cast<const char*>(this) + sizeof(*this)); 204 reinterpret_cast<const char*>(this) + sizeof(*this));
292 } 205 }
293 206
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) { 207 void EncodePointersAndHandles(std::vector<Handle>* handles) {
317 Helper::EncodePointersAndHandles(&header_, storage(), handles); 208 Helper::EncodePointersAndHandles(&header_, storage(), handles);
318 } 209 }
319 210
320 bool DecodePointersAndHandles(Message* message) { 211 bool DecodePointersAndHandles(Message* message) {
321 return Helper::DecodePointersAndHandles(&header_, storage(), message); 212 return Helper::DecodePointersAndHandles(&header_, storage(), message);
322 } 213 }
323 214
324 private: 215 private:
325 Array_Data(size_t num_bytes, size_t num_elements) { 216 Array_Data(size_t num_bytes, size_t num_elements) {
326 header_.num_bytes = static_cast<uint32_t>(num_bytes); 217 header_.num_bytes = static_cast<uint32_t>(num_bytes);
327 header_.num_elements = static_cast<uint32_t>(num_elements); 218 header_.num_elements = static_cast<uint32_t>(num_elements);
328 } 219 }
329 ~Array_Data() {} 220 ~Array_Data() {}
330 221
331 internal::ArrayHeader header_; 222 internal::ArrayHeader header_;
332 223
333 // Elements of type internal::ArrayDataTraits<T>::StorageType follow. 224 // Elements of type internal::ArrayDataTraits<T>::StorageType follow.
334 }; 225 };
335 MOJO_COMPILE_ASSERT(sizeof(Array_Data<char>) == 8, bad_sizeof_Array_Data); 226 MOJO_COMPILE_ASSERT(sizeof(Array_Data<char>) == 8, bad_sizeof_Array_Data);
336 227
337 // UTF-8 encoded 228 // UTF-8 encoded
338 typedef Array_Data<char> String_Data; 229 typedef Array_Data<char> String_Data;
339 230
340 template <typename T, bool kIsObject, bool kIsHandle> struct ArrayTraits {}; 231 template <typename T, bool kIsMoveOnlyType> struct ArrayTraits {};
341 232
342 // When T is an object type: 233 template <typename T> struct ArrayTraits<T, false> {
343 template <typename T> struct ArrayTraits<T, true, false> { 234 typedef T StorageType;
344 typedef Array_Data<typename T::Data*> DataType; 235 typedef typename std::vector<T>::reference RefType;
345 typedef const T& ConstRef; 236 typedef typename std::vector<T>::const_reference ConstRefType;
346 typedef T& Ref; 237 static inline void Initialize(std::vector<T>* vec) {
347 static Buffer::Destructor GetDestructor() {
348 return NULL;
349 } 238 }
350 static typename T::Data* ToArrayElement(const T& value) { 239 static inline void Finalize(std::vector<T>* vec) {
351 return Unwrap(value);
352 } 240 }
353 // Something sketchy is indeed happening here... 241 static inline ConstRefType at(const std::vector<T>* vec, size_t offset) {
354 static Ref ToRef(typename T::Data*& data) { 242 return vec->at(offset);
355 return *reinterpret_cast<T*>(&data);
356 } 243 }
357 static ConstRef ToConstRef(typename T::Data* const& data) { 244 static inline RefType at(std::vector<T>* vec, size_t offset) {
358 return *reinterpret_cast<const T*>(&data); 245 return vec->at(offset);
359 } 246 }
360 }; 247 };
361 248
362 // When T is a primitive (non-bool) type: 249 template <typename T> struct ArrayTraits<T, true> {
363 template <typename T> struct ArrayTraits<T, false, false> { 250 struct StorageType {
364 typedef Array_Data<T> DataType; 251 char buf[sizeof(T) + (8 - (sizeof(T) % 8)) % 8]; // Make 8-byte aligned.
365 typedef const T& ConstRef; 252 };
366 typedef T& Ref; 253 typedef T& RefType;
367 static Buffer::Destructor GetDestructor() { 254 typedef const T& ConstRefType;
368 return NULL; 255 static inline void Initialize(std::vector<StorageType>* vec) {
256 for (size_t i = 0; i < vec->size(); ++i)
257 new (vec->at(i).buf) T();
369 } 258 }
370 static T ToArrayElement(const T& value) { 259 static inline void Finalize(std::vector<StorageType>* vec) {
371 return value; 260 for (size_t i = 0; i < vec->size(); ++i)
261 reinterpret_cast<T*>(vec->at(i).buf)->~T();
372 } 262 }
373 static Ref ToRef(T& data) { return data; } 263 static inline ConstRefType at(const std::vector<StorageType>* vec,
374 static ConstRef ToConstRef(const T& data) { return data; } 264 size_t offset) {
375 }; 265 return *reinterpret_cast<const T*>(vec->at(offset).buf);
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 } 266 }
385 static bool ToArrayElement(const bool& value) { 267 static inline RefType at(std::vector<StorageType>* vec, size_t offset) {
386 return value; 268 return *reinterpret_cast<T*>(vec->at(offset).buf);
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 } 269 }
407 }; 270 };
408 271
272 template <> struct WrapperTraits<String, false> {
273 typedef String_Data* DataType;
274 };
275
409 } // namespace internal 276 } // namespace internal
410 } // namespace mojo 277 } // namespace mojo
411 278
412 #endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_ARRAY_INTERNAL_H_ 279 #endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_ARRAY_INTERNAL_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698