1 /+
2  +  Wayland copyright:
3  +  Copyright © 2008 Kristian Høgsberg
4  +
5  +  Permission is hereby granted, free of charge, to any person
6  +  obtaining a copy of this software and associated documentation files
7  +  (the "Software"), to deal in the Software without restriction,
8  +  including without limitation the rights to use, copy, modify, merge,
9  +  publish, distribute, sublicense, and/or sell copies of the Software,
10  +  and to permit persons to whom the Software is furnished to do so,
11  +  subject to the following conditions:
12  +
13  +  The above copyright notice and this permission notice (including the
14  +  next paragraph) shall be included in all copies or substantial
15  +  portions of the Software.
16  +
17  +  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18  +  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19  +  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20  +  NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
21  +  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
22  +  ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23  +  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24  +  SOFTWARE.
25  +/
26 /+
27  +  D bindings copyright:
28  +  Copyright © 2015 Rémi Thebault
29  +/
30 module wayland.client.util;
31 
32 import wayland.client.opaque_types;
33 import std.range;
34 
35 
36 enum WAYLAND_VERSION_MAJOR = 1;
37 enum WAYLAND_VERSION_MINOR = 8;
38 enum WAYLAND_VERSION_MICRO = 90;
39 enum WAYLAND_VERSION = "1.8.90";
40 
41 
42 
43 extern (C) {
44 
45 
46 
47     struct wl_message {
48         const (char*) name;
49         const (char*) signature;
50         const (wl_interface*)* types;
51     }
52 
53     struct wl_interface {
54         const (char*) name;
55         int ver;
56         int method_count;
57         const (wl_message*) methods;
58         int event_count;
59         const (wl_message*) events;
60     }
61 
62     /** \class wl_list
63     *
64     * \brief doubly-linked list
65     *
66     * The list head is of "struct wl_list" type, and must be initialized
67     * using wl_list_init().  All entries in the list must be of the same
68     * type.  The item type must have a "struct wl_list" member. This
69     * member will be initialized by wl_list_insert(). There is no need to
70     * call wl_list_init() on the individual item. To query if the list is
71     * empty in O(1), use wl_list_empty().
72     *
73     * Let's call the list reference "struct wl_list foo_list", the item type as
74     * "item_t", and the item member as "struct wl_list link".
75     *
76     * The following code will initialize a list:
77     * \code
78     * struct wl_list foo_list;
79     *
80     * struct item_t {
81     *     int foo;
82     *     struct wl_list link;
83     * };
84     * struct item_t item1, item2, item3;
85     *
86     * wl_list_init(&foo_list);
87     * wl_list_insert(&foo_list, &item1.link);    // Pushes item1 at the head
88     * wl_list_insert(&foo_list, &item2.link);    // Pushes item2 at the head
89     * wl_list_insert(&item2.link, &item3.link);    // Pushes item3 after item2
90     * \endcode
91     *
92     * The list now looks like [item2, item3, item1]
93     *
94     * Iterate the list in ascending order:
95     * \code
96     * item_t *item;
97     * wl_list_for_each(item, foo_list, link) {
98     *     Do_something_with_item(item);
99     * }
100     * \endcode
101     */
102     struct wl_list {
103         wl_list *prev;
104         wl_list *next;
105     }
106 
107 
108 
109     struct wl_array {
110         size_t size;
111         size_t alloc;
112         void *data;
113     }
114 
115 
116 
117 
118     alias wl_fixed_t = int;
119 
120 
121 
122     /**
123     * \brief A union representing all of the basic data types that can be passed
124     * along the wayland wire format.
125     *
126     * This union represents all of the basic data types that can be passed in the
127     * wayland wire format.  It is used by dispatchers and runtime-friendly
128     * versions of the event and request marshaling functions.
129     */
130     union wl_argument {
131         int i; /**< signed integer */
132         uint u; /**< unsigned integer */
133         wl_fixed_t f; /**< fixed point */
134         const (char*) s; /**< string */
135         wl_object *o; /**< object */
136         uint n; /**< new_id */
137         wl_array *a; /**< array */
138         int h; /**< file descriptor */
139     }
140 
141     /**
142     * \brief A function pointer type for a dispatcher.
143     *
144     * A dispatcher is a function that handles the emitting of callbacks in client
145     * code.  For programs directly using the C library, this is done by using
146     * libffi to call function pointers.  When binding to languages other than C,
147     * dispatchers provide a way to abstract the function calling process to be
148     * friendlier to other function calling systems.
149     *
150     * A dispatcher takes five arguments:  The first is the dispatcher-specific
151     * implementation data associated with the target object.  The second is the
152     * object on which the callback is being invoked (either wl_proxy or
153     * wl_resource).  The third and fourth arguments are the opcode the wl_messsage
154     * structure corresponding to the callback being emitted.  The final argument
155     * is an array of arguments received from the other process via the wire
156     * protocol.
157     */
158     alias wl_dispatcher_func_t = int function (const (void*), void*, uint,
159             const (wl_message*), wl_argument*);
160 
161     alias wl_log_func_t = void function (const (char*), ...);
162 
163 }
164 
165 /**
166  * Retrieves a pointer to the containing struct of a given member item.
167  *
168  * This macro allows conversion from a pointer to a item to its containing
169  * struct. This is useful if you have a contained item like a wl_list,
170  * wl_listener, or wl_signal, provided via a callback or other means and would
171  * like to retrieve the struct that contains it.
172  *
173  * To demonstrate, the following example retrieves a pointer to
174  * `example_container` given only its `destroy_listener` member:
175  *
176  * \code
177  * struct example_container {
178  *     struct wl_listener destroy_listener;
179  *     // other members...
180  * };
181  *
182  * void example_container_destroy(struct wl_listener *listener, void *data)
183  * {
184  *     struct example_container *ctr;
185  *
186  *     ctr = wl_container_of(listener, ctr, destroy_listener);
187  *     // destroy ctr...
188  * }
189  * \endcode
190  *
191  * \param ptr A valid pointer to the contained item.
192  *
193  * \param sample A pointer to the type of content that the list item
194  * stores. Sample does not need be a valid pointer; a null or
195  * an uninitialised pointer will suffice.
196  *
197  * \param member The named location of ptr within the sample type.
198  *
199  * \return The container for the specified pointer.
200  */
201 template wl_container_of(alias member)
202 {
203     static ParentOf!member* wl_container_of(T)(T* ptr)
204     {
205         return cast(ParentOf!member*)(cast(ptrdiff_t)(ptr)-member.offsetof);
206     }
207 }
208 
209 unittest {
210 
211     struct S {
212         string foo;
213         int bar;
214     }
215 
216     S s;
217     assert(wl_container_of!(S.bar)(&s.bar) == &s);
218 }
219 
220 
221 template wl_range(alias member)
222 {
223     static WlListRange!member wl_range(wl_list *head)
224     {
225         return WlListRange!member(head);
226     }
227 }
228 
229 unittest
230 {
231     struct Item
232     {
233         int num;
234         wl_list link;
235 
236         this(int num) { this.num = num; }
237     }
238     auto i1 = Item(1);
239     auto i2 = Item(2);
240     auto i3 = Item(3);
241 
242     wl_list lst;
243     wl_list_init(&lst);
244     wl_list_insert(&lst, &i1.link);
245     wl_list_insert(&lst, &i2.link);
246     wl_list_insert(&i2.link, &i3.link);
247 
248     int[] forw_arr;
249     foreach(it; wl_range!(Item.link)(&lst)) {
250         forw_arr ~= it.num;
251     }
252     assert(forw_arr == [2, 3, 1]);
253 
254     int[] back_arr;
255     foreach_reverse(it; wl_range!(Item.link)(&lst)) {
256         back_arr ~= it.num;
257     }
258     assert(back_arr == [1, 3, 2]);
259 }
260 
261 
262 
263 
264 template wl_range(T)
265 {
266     static WlArrayRange!T wl_range(wl_array *arr)
267     {
268         return WlArrayRange!T(arr);
269     }
270 }
271 
272 unittest
273 {
274     wl_array arr;
275     wl_array_init(&arr);
276 
277     foreach(i; 0..1342) {
278         int *ptr = cast(int*)wl_array_add(&arr, int.sizeof);
279         *ptr = i*12 - 15;
280 
281     }
282 
283     int ind=0;
284     foreach(pi; wl_range!(int)(&arr)) {
285         assert(*pi == ind++*12-15);
286     }
287     assert(ind==1342);
288 
289     wl_array_release(&arr);
290 }
291 
292 
293 
294 double
295 wl_fixed_to_double (wl_fixed_t f)
296 {
297     union di {
298         double d;
299         long i;
300     }
301     di u;
302 
303     u.i = ((1023L + 44L) << 52) + (1L << 51) + f;
304 
305     return u.d - (3L << 43);
306 }
307 
308 wl_fixed_t
309 wl_fixed_from_double(double d)
310 {
311     union di {
312         double d;
313         long i;
314     }
315     di u;
316 
317     u.d = d + (3L << (51 - 8));
318 
319     return cast(wl_fixed_t)u.i;
320 }
321 
322 int wl_fixed_to_int(wl_fixed_t f)
323 {
324     return f / 256;
325 }
326 wl_fixed_t wl_fixed_from_int(int i)
327 {
328     return i * 256;
329 }
330 
331 
332 
333 
334 private {
335 
336     template Id(alias a) { alias Id = a; }
337 
338 
339     template ParentOf(alias member)
340     {
341         alias ParentOf = Id!(__traits(parent, member));
342     }
343 
344     struct WlListRange(alias member)
345     {
346         wl_list *head;
347         wl_list *fpos;
348         wl_list *bpos;
349 
350         alias ElType = ParentOf!member;
351 
352         this(wl_list *head)
353         {
354             this.head = head;
355             fpos = head.next;
356             bpos = head.prev;
357         }
358 
359         // input
360 
361         @property bool empty() const {
362             return fpos == head || bpos == head;
363         }
364 
365         @property ElType *front() {
366             return wl_container_of!member(fpos);
367         }
368 
369         void popFront() {
370             fpos = fpos.next;
371         }
372 
373         // forward
374 
375         @property WlListRange!member save() {
376             return this;
377         }
378 
379         // bidirectional
380 
381         @property ElType *back() {
382             return wl_container_of!member(bpos);
383         }
384 
385         void popBack() {
386             bpos = bpos.prev;
387         }
388     }
389 
390 
391     struct Item
392     {
393         int num;
394         wl_list link;
395 
396         this(int num) { this.num = num; }
397     }
398 
399     static assert(isBidirectionalRange!(WlListRange!(Item.link)));
400 
401 
402     struct WlArrayRange(T)
403     {
404         wl_array *arr;
405         size_t fpos;
406         size_t bpos;
407 
408         this (wl_array *arr)
409         {
410             assert(arr.size % T.sizeof == 0);
411             this.arr = arr;
412             fpos = 0;
413             bpos = arr.size / T.sizeof;
414         }
415 
416         // input
417 
418         @property bool empty() const {
419             return fpos == arr.size / T.sizeof || bpos == 0;
420         }
421 
422         @property inout(T)* front() inout {
423             return cast(inout(T)*)(arr.data + fpos*T.sizeof);
424         }
425 
426         void popFront() {
427             ++fpos;
428         }
429 
430 
431         // forward
432 
433         @property WlArrayRange!T save() {
434             return this;
435         }
436 
437 
438         // bidirectional
439 
440         @property inout(T)* back() inout {
441             return cast(inout(T)*)(arr.data + bpos*T.sizeof);
442         }
443 
444         void popBack() {
445             --bpos;
446         }
447 
448 
449         // random access
450 
451         @property size_t length() const {
452             return arr.size / T.sizeof;
453         }
454 
455         inout(T)* opIndex(size_t n) inout {
456             return cast(inout(T)*)(arr.data + n*T.sizeof);
457         }
458 
459     }
460 
461     static assert(isRandomAccessRange!(WlArrayRange!int));
462 
463 
464 }
465 
466 
467 version (Dynamic) {
468     extern (C) {
469         alias da_wl_list_init           = void  function (wl_list *list);
470         alias da_wl_list_insert         = void  function (wl_list *list, wl_list *elm);
471         alias da_wl_list_remove         = void  function (wl_list *elm);
472         alias da_wl_list_length         = int   function (const (wl_list*) list);
473         alias da_wl_list_empty          = int   function (const (wl_list*) list);
474         alias da_wl_list_insert_list    = void  function (wl_list *list, wl_list *other);
475 
476         alias da_wl_array_init          = void  function (wl_array *array);
477         alias da_wl_array_release       = void  function (wl_array *array);
478         alias da_wl_array_add           = void *function (wl_array *array, size_t size);
479         alias da_wl_array_copy          = int   function (wl_array *array, wl_array *source);
480     }
481     __gshared {
482 
483         da_wl_list_init         wl_list_init;
484         da_wl_list_insert       wl_list_insert;
485         da_wl_list_remove       wl_list_remove;
486         da_wl_list_length       wl_list_length;
487         da_wl_list_empty        wl_list_empty;
488         da_wl_list_insert_list  wl_list_insert_list;
489 
490         da_wl_array_init        wl_array_init;
491         da_wl_array_release     wl_array_release;
492         da_wl_array_add         wl_array_add;
493         da_wl_array_copy        wl_array_copy;
494     }
495 
496 }
497 else {
498     extern (C) {
499         void    wl_list_init        (wl_list *list);
500         void    wl_list_insert      (wl_list *list, wl_list *elm);
501         void    wl_list_remove      (wl_list *elm);
502         int     wl_list_length      (const (wl_list*) list);
503         int     wl_list_empty       (const (wl_list*) list);
504         void    wl_list_insert_list (wl_list *list, wl_list *other);
505 
506         void    wl_array_init       (wl_array *array);
507         void    wl_array_release    (wl_array *array);
508         void *  wl_array_add        (wl_array *array, size_t size);
509         int     wl_array_copy       (wl_array *array, wl_array *source);
510     }
511 }
512 
513 
514