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

Side by Side Diff: mojo/public/bindings/test.cc

Issue 23913008: C++ bindings (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 2 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
« no previous file with comments | « mojo/mojo.gyp ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /*
2 // HYPOTHETICAL IDL:
3
4 struct Bar {
5 alpha @0 :uint8;
6 beta @1 :uint8;
7 gamma @2 :uint8;
8 };
9
10 struct Foo {
11 x @0 :int32;
12 y @1 :int32;
13 a @2 :bool;
14 b @3 :bool;
15 c @4 :bool;
16 bar @5 :Bar;
17 extra_bars @7 :array(Bar) [optional];
18 data @6 :array(uint8);
19 };
20
21 interface Blah {
22 Frobinate @0 (foo @0 :Foo, baz @1 :bool);
23 };
24
25 */
26
27 #include <stddef.h>
28 #include <stdint.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <vector>
33
34 // This would be part of some header file we'd provide.
35
36 typedef uint32_t Handle;
37
38 struct Message {
39 uint32_t name;
40 uint8_t* data_start;
41 uint8_t* data_end;
42 Handle* handles_start;
43 Handle* handles_end;
44 };
45
46 struct StructHeader {
47 uint32_t num_bytes;
48 uint32_t num_fields;
49 };
50
51 struct ArrayHeader {
52 uint32_t num_bytes;
53 uint32_t num_elements;
54 };
55
56 template <typename T> class Array;
57
58 template <typename T>
59 union StructPointer {
60 uint64_t offset;
61 T* ptr;
62 };
63
64 template <typename T>
65 union ArrayPointer {
66 uint64_t offset;
67 Array<T>* ptr;
68 };
69
70 inline void EncodePointer(void* address, uint64_t* offset) {
71 if (!address) {
72 *offset = 0;
73 return;
74 }
75 uint8_t* p_obj = reinterpret_cast<uint8_t*>(address);
76 uint8_t* p_slot = reinterpret_cast<uint8_t*>(offset);
77 *offset = p_obj - p_slot;
yzshen1 2013/09/24 18:32:56 Is it intended to use an unsigned number for |offs
78 }
79
80 template <typename T>
81 inline void DecodePointer(uint64_t* offset, T** ptr) {
82 if (!*offset) {
83 *ptr = NULL;
84 return;
85 }
86 uint8_t* p_slot = reinterpret_cast<uint8_t*>(offset);
87 *ptr = reinterpret_cast<T*>(p_slot + *offset);
88 }
89
90 template <typename T>
91 struct ArrayTraits {
92 typedef T ElementType;
93
94 static T& ToElementRef(ElementType& e) { return e; }
95 static T const& ToElementConstRef(const ElementType& e) { return e; }
96
97 static void EncodePointersAndHandles(ArrayHeader* header,
98 ElementType* elements,
99 std::vector<Handle>* handles) {
100 }
101 static bool DecodePointersAndHandles(ArrayHeader* header,
102 ElementType* elements,
103 const Message& message) {
104 return true;
105 }
106 };
107
108 template <typename P>
109 struct ArrayTraits<P*> {
110 typedef StructPointer<P> ElementType;
111
112 static P*& ToElementRef(ElementType& e) { return e.ptr; }
113 static P* const& ToElementConstRef(const ElementType& e) { return e.ptr; }
114
115 static void EncodePointersAndHandles(ArrayHeader* header,
116 ElementType* elements,
117 std::vector<Handle>* handles) {
118 for (uint32_t i = 0; i < header->num_elements; ++i) {
119 if (elements[i].ptr)
120 elements[i].ptr->EncodePointersAndHandles(handles);
121 EncodePointer(elements[i].ptr, &elements[i].offset);
122 }
123 }
124 static bool DecodePointersAndHandles(ArrayHeader* header,
125 ElementType* elements,
126 const Message& message) {
127 for (uint32_t i = 0; i < header->num_elements; ++i) {
128 DecodePointer(&elements[i].offset, &elements[i].ptr);
129 if (elements[i].ptr)
130 elements[i].ptr->DecodePointersAndHandles(message);
131 }
132 return true;
133 }
134 };
135
136 template <typename T>
137 class Array {
138 public:
139 void Initialize(size_t num_elements) {
140 // TODO: bools should get packed to a single bit?
141 header_.num_bytes =
142 sizeof(typename ArrayTraits<T>::ElementType) * num_elements -
143 sizeof(ArrayHeader);
144 header_.num_elements = num_elements;
145 }
146
147 void EncodePointersAndHandles(std::vector<Handle>* handles) {
148 ArrayTraits<T>::EncodePointersAndHandles(&header_, elements_, handles);
149 }
150 bool DecodePointersAndHandles(const Message& message) {
151 return ArrayTraits<T>::DecodePointersAndHandles(&header_, elements_,
152 message);
153 }
154
155 size_t size() const { return header_.num_elements; }
156
157 T& at(size_t offset) {
158 return ArrayTraits<T>::ToElementRef(elements_[offset]);
159 }
160
161 const T& at(size_t offset) const {
162 return ArrayTraits<T>::ToElementConstRef(elements_[offset]);
163 }
164
165 T& operator[](size_t offset) {
166 return ArrayTraits<T>::ToElementRef(elements_[offset]);
167 }
168
169 const T& operator[](size_t offset) const {
170 return ArrayTraits<T>::ToElementConstRef(elements_[offset]);
171 }
172
173 private:
174 ArrayHeader header_;
175 typename ArrayTraits<T>::ElementType elements_[1];
176 };
177
178 //----
179 // Begin generated code.
180
181 // What follows is class definitions corresponding to the structures indicated
182 // by the IDL.
183
184 class Bar {
185 public:
186 void Initialize() {
187 header_.num_bytes = sizeof(*this) - sizeof(StructHeader);
188 header_.num_fields = 3;
189 }
190
191 void EncodePointersAndHandles(std::vector<Handle>* handles) {
192 }
193 bool DecodePointersAndHandles(const Message& message) {
194 return true;
195 }
196
197 void set_alpha(uint8_t alpha) { d_.alpha = alpha; }
198 void set_beta(uint8_t beta) { d_.beta = beta; }
199 void set_gamma(uint8_t gamma) { d_.gamma = gamma; }
200
201 uint8_t alpha() const { return d_.alpha; }
202 uint8_t beta() const { return d_.beta; }
203 uint8_t gamma() const { return d_.gamma; }
204
205 private:
206 StructHeader header_;
207 struct {
208 uint8_t alpha;
209 uint8_t beta;
210 uint8_t gamma;
211 } d_;
212
213 // NOT IMPLEMENTED
214 Bar();
215 ~Bar();
216 };
217
218 class Foo {
219 public:
220 void Initialize() {
221 header_.num_bytes = sizeof(*this) - sizeof(StructHeader);
222 header_.num_fields = 8;
223 }
224
225 void EncodePointersAndHandles(std::vector<Handle>* handles) {
226 if (d_.bar.ptr)
227 d_.bar.ptr->EncodePointersAndHandles(handles);
228 EncodePointer(d_.bar.ptr, &d_.bar.offset);
229
230 if (d_.data.ptr)
231 d_.data.ptr->EncodePointersAndHandles(handles);
232 EncodePointer(d_.data.ptr, &d_.data.offset);
233
234 if (d_.extra_bars.ptr)
235 d_.extra_bars.ptr->EncodePointersAndHandles(handles);
236 EncodePointer(d_.extra_bars.ptr, &d_.extra_bars.offset);
237 }
238
239 bool DecodePointersAndHandles(const Message& message) {
240 DecodePointer(&d_.bar.offset, &d_.bar.ptr);
241 if (d_.bar.ptr) {
242 if (!d_.bar.ptr->DecodePointersAndHandles(message))
243 return false;
244 }
245
246 DecodePointer(&d_.data.offset, &d_.data.ptr);
247 if (d_.data.ptr) {
248 if (!d_.data.ptr->DecodePointersAndHandles(message))
249 return false;
250 }
251
252 if (header_.num_fields >= 8) {
253 DecodePointer(&d_.extra_bars.offset, &d_.extra_bars.ptr);
254 if (d_.extra_bars.ptr) {
255 if (!d_.extra_bars.ptr->DecodePointersAndHandles(message))
256 return false;
257 }
258 }
259
260 // TODO: validate
261 return true;
262 }
263
264 void set_x(int32_t x) { d_.x = x; }
265 void set_y(int32_t y) { d_.y = y; }
266 void set_a(bool a) { d_.a = a; }
267 void set_b(bool b) { d_.b = b; }
268 void set_c(bool c) { d_.c = c; }
269 void set_bar(Bar* bar) { d_.bar.ptr = bar; }
270 void set_data(Array<uint8_t>* data) { d_.data.ptr = data; }
271 void set_extra_bars(Array<Bar*>* extra_bars) {
272 d_.extra_bars.ptr = extra_bars;
273 }
274
275 int32_t x() const { return d_.x; }
276 int32_t y() const { return d_.y; }
277 bool a() const { return d_.a; }
278 bool b() const { return d_.b; }
279 bool c() const { return d_.c; }
280 const Bar* bar() const { return d_.bar.ptr; }
281 const Array<uint8_t>* data() const { return d_.data.ptr; }
282 const Array<Bar*>* extra_bars() const {
283 // NOTE: extra_bars is an optional field!
284 return header_.num_fields >= 8 ? d_.extra_bars.ptr : NULL;
285 }
286
287 private:
288 StructHeader header_;
289 struct {
290 int32_t x;
291 int32_t y;
292 uint32_t a : 1;
293 uint32_t b : 1;
294 uint32_t c : 1;
295 StructPointer<Bar> bar;
296 ArrayPointer<uint8_t> data;
297 ArrayPointer<Bar*> extra_bars;
298 } d_;
299
300 // NOT IMPLEMENTED
301 Foo();
302 ~Foo();
303 };
304
305 class Frobinate_Params {
306 public:
307 void Initialize() {
308 header_.num_bytes = sizeof(*this) - sizeof(StructHeader);
309 header_.num_fields = 2;
310 }
311
312 void EncodePointersAndHandles(std::vector<Handle>* handles) {
313 if (d_.foo.ptr)
314 d_.foo.ptr->EncodePointersAndHandles(handles);
315 EncodePointer(d_.foo.ptr, &d_.foo.offset);
316 }
317 bool DecodePointersAndHandles(const Message& message) {
318 DecodePointer(&d_.foo.offset, &d_.foo.ptr);
319 if (d_.foo.ptr) {
320 if (!d_.foo.ptr->DecodePointersAndHandles(message))
321 return false;
322 }
323 // TODO: validate
324 return true;
325 }
326
327 void set_foo(Foo* foo) { d_.foo.ptr = foo; }
328 void set_baz(bool baz) { d_.baz = baz; }
329
330 const Foo* foo() const { return d_.foo.ptr; }
331 bool baz() const { return d_.baz; }
332
333 private:
334 StructHeader header_;
335 struct {
336 StructPointer<Foo> foo;
337 uint32_t baz : 1;
338 } d_;
339
340 // NOT IMPLEMENTED
341 Frobinate_Params();
342 ~Frobinate_Params();
343 };
344
345 const uint32_t kMessageID_Frobinate = 1;
346
347 //----
348 // The following code would also be generated by our bindings system.
349
350 class Blah {
351 public:
352 virtual void Frobinate(const Foo* foo, bool baz) = 0;
353 };
354
355 class BlahStub : public Blah {
356 public:
357 bool OnMessageReceived(const Message& message) {
358 switch (message.name) {
359 case kMessageID_Frobinate: {
360 Frobinate_Params* params =
361 reinterpret_cast<Frobinate_Params*>(message.data_start);
362 if (!params->DecodePointersAndHandles(message))
363 return false;
364 Frobinate(params->foo(), params->baz());
365 break;
366 }
367 }
368 return true;
369 }
370 };
371
372 #if 0
373 // TODO: Figure out how to make the client-side work nicely.
374 class BlahProxy : public Blah {
375 public:
376 virtual void SendMessage(const Message& message) = 0;
377
378 virtual void Frobinate(const Foo* foo, bool baz) {
379 }
380
381 virtual void Frobinate(const Frobinate_Params* params) {
382 }
383 };
384 #endif
385
386 //----
387 // User code goes here:
388
389 static void PrintSpacer(int depth) {
390 for (int i = 0; i < depth; ++i)
391 printf(" ");
392 }
393
394 static void Print(int depth, const char* name, bool value) {
395 PrintSpacer(depth);
396 printf("%s: %s\n", name, value ? "true" : "false");
397 }
398
399 static void Print(int depth, const char* name, int32_t value) {
400 PrintSpacer(depth);
401 printf("%s: %d\n", name, value);
402 }
403
404 static void Print(int depth, const char* name, uint8_t value) {
405 PrintSpacer(depth);
406 printf("%s: %u\n", name, value);
407 }
408
409 template <typename T>
410 static void Print(int depth, const char* name, const Array<T>* array) {
411 PrintSpacer(depth);
412 printf("%s: %p\n", name, array);
413 if (array) {
414 ++depth;
415 for (size_t i = 0; i < array->size(); ++i) {
416 char buf[32];
417 sprintf(buf, "%lu", i);
418 Print(depth, buf, array->at(i));
419 }
420 --depth;
421 }
422 }
423
424 static void Print(int depth, const char* name, const Bar* bar) {
425 PrintSpacer(depth);
426 printf("%s: %p\n", name, bar);
427 if (bar) {
428 ++depth;
429 Print(depth, "alpha", bar->alpha());
430 Print(depth, "beta", bar->beta());
431 Print(depth, "gamma", bar->gamma());
432 --depth;
433 }
434 }
435
436 static void Print(int depth, const char* name, const Foo* foo) {
437 PrintSpacer(depth);
438 printf("%s: %p\n", name, foo);
439 if (foo) {
440 ++depth;
441 Print(depth, "x", foo->x());
442 Print(depth, "y", foo->y());
443 Print(depth, "a", foo->a());
444 Print(depth, "b", foo->b());
445 Print(depth, "c", foo->c());
446 Print(depth, "bar", foo->bar());
447 Print(depth, "data", foo->data());
448 Print(depth, "extra_bars", foo->extra_bars());
449 --depth;
450 }
451 }
452
453 class BlahImpl : public BlahStub {
454 public:
455 virtual void Frobinate(const Foo* foo, bool baz) {
456 // Users code goes here to handle the incoming Frobinate message.
457 // We'll just dump the Foo structure and all of its members.
458
459 printf("Frobinate:\n");
460
461 int depth = 1;
462 Print(depth, "foo", foo);
463 Print(depth, "baz", baz);
464 }
465 };
466
467 //----
468
469 // The following is just some cheezy buffer allocation code.
470 // We'd want to sugar this somehow.
471
472 class Buffer {
473 public:
474 Buffer() : ptr_(NULL), size_(0) {
475 }
476 ~Buffer() { free(ptr_); }
477
478 const uint8_t* data() const { return ptr_; }
479 uint8_t* data() { return ptr_; }
480
481 size_t size() const { return size_; }
482
483 template <typename T>
484 T* Alloc() {
485 T* ptr = reinterpret_cast<T*>(Grow(sizeof(T)));
486 ptr->Initialize();
487 return ptr;
488 }
489
490 template <typename T>
491 Array<T>* AllocArray(size_t count) {
492 Array<T>* ptr = reinterpret_cast<Array<T>*>(
493 Grow(sizeof(Array<T>) + sizeof(T) * (count - 1)));
494 ptr->Initialize(count);
495 return ptr;
496 }
497
498 private:
499 uint8_t* Grow(size_t delta) {
500 size_t old_size = size_;
501 size_t new_size = old_size + delta;
502 ptr_ = static_cast<uint8_t*>(realloc(ptr_, old_size + delta));
503 size_ = new_size;
504 uint8_t* result = ptr_ + old_size;
505 memset(result, 0, delta);
506 return result;
507 }
508
509 uint8_t* ptr_;
510 size_t size_;
511
512 // NOT IMPLEMENTED
513 Buffer(const Buffer&);
514 void operator=(const Buffer&);
515 };
516
517 int main() {
518 // User constructs a message to send. TODO: Add more sugar to this!
519
520 Buffer buf;
521
522 Frobinate_Params* params = buf.Alloc<Frobinate_Params>();
523 params->set_baz(true);
524
525 Foo* foo = buf.Alloc<Foo>();
526 foo->set_x(1);
527 foo->set_y(2);
528 foo->set_a(false);
529 foo->set_b(true);
530 foo->set_c(false);
531
532 Bar* bar = buf.Alloc<Bar>();
533 bar->set_alpha(20);
534 bar->set_beta(40);
535 bar->set_gamma(60);
536 foo->set_bar(bar);
537
538 const size_t kNumDataElements = 10;
539 Array<uint8_t>* data = buf.AllocArray<uint8_t>(kNumDataElements);
540 for (size_t i = 0; i < kNumDataElements; ++i)
541 data->at(i) = static_cast<uint8_t>(kNumDataElements - i);
542 foo->set_data(data);
543
544 const size_t kNumExtraBarsElements = 3;
545 Array<Bar*>* extra_bars = buf.AllocArray<Bar*>(kNumExtraBarsElements);
546 for (size_t i = 0; i < kNumExtraBarsElements; ++i) {
547 Bar* bar = buf.Alloc<Bar>();
548 bar->set_alpha(i * 100);
549 bar->set_beta(i * 100 + 20);
550 bar->set_gamma(i * 100 + 40);
551 extra_bars->at(i) = bar;
552 }
553 foo->set_extra_bars(extra_bars);
554
555 params->set_foo(foo);
556
557 // Last step before sending the message is to encode pointers and handles so
558 // that messages become hermetic. Pointers become offsets and handles becomes
559 // indices into the handles array.
560
561 std::vector<Handle> handles;
562 params->EncodePointersAndHandles(&handles);
563
564 Message message;
565 message.name = kMessageID_Frobinate;
566 message.data_start = buf.data();
567 message.data_end = buf.data() + buf.size();
568 message.handles_start = &handles[0];
569 message.handles_end = &handles[0] + handles.size();
570
571 // At this point, the user would normally call WriteMessage to write buf
572 // to a pipe. Here, we are leaving that part out. We'll just forward buf
573 // as a simulated incoming message to the generated bindings for handling
574 // a message. OnMessageReceived would ordinarily be prefixed with a call
575 // to ReadMessage to read an incoming message from a pipe.
576
577 BlahStub* stub = new BlahImpl();
578 stub->OnMessageReceived(message);
579 return 0;
580 }
OLDNEW
« no previous file with comments | « mojo/mojo.gyp ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698