1 // Copyright © 2017-2021 Rémi Thebault 2 /// bindings to wayland-util.h 3 module wayland.native.util; 4 5 // Wayland util copyright: 6 /* 7 * Copyright © 2008 Kristian Høgsberg 8 * 9 * Permission is hereby granted, free of charge, to any person obtaining 10 * a copy of this software and associated documentation files (the 11 * "Software"), to deal in the Software without restriction, including 12 * without limitation the rights to use, copy, modify, merge, publish, 13 * distribute, sublicense, and/or sell copies of the Software, and to 14 * permit persons to whom the Software is furnished to do so, subject to 15 * the following conditions: 16 * 17 * The above copyright notice and this permission notice (including the 18 * next paragraph) shall be included in all copies or substantial 19 * portions of the Software. 20 * 21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 22 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 23 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 24 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 25 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 26 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 27 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 28 * SOFTWARE. 29 */ 30 31 import core.stdc.stdarg : va_list; 32 33 extern(C) nothrow 34 { 35 /** 36 * Protocol message signature 37 * 38 * A wl_message describes the signature of an actual protocol message, such as a 39 * request or event, that adheres to the Wayland protocol wire format. The 40 * protocol implementation uses a wl_message within its demarshal machinery for 41 * decoding messages between a compositor and its clients. In a sense, a 42 * wl_message is to a protocol message like a class is to an object. 43 * 44 * The `name` of a wl_message is the name of the corresponding protocol message. 45 * The `signature` is an ordered list of symbols representing the data types 46 * of message arguments and, optionally, a protocol version and indicators for 47 * nullability. A leading integer in the `signature` indicates the _since_ 48 * version of the protocol message. A `?` preceding a data type symbol indicates 49 * that the following argument type is nullable. When no arguments accompany a 50 * message, `signature` is an empty string. 51 * 52 * * `i`: int 53 * * `u`: uint 54 * * `f`: fixed 55 * * `s`: string 56 * * `o`: object 57 * * `n`: new_id 58 * * `a`: array 59 * * `h`: fd 60 * * `?`: following argument is nullable 61 * 62 * While demarshaling primitive arguments is straightforward, when demarshaling 63 * messages containing `object` or `new_id` arguments, the protocol 64 * implementation often must determine the type of the object. The `types` of a 65 * wl_message is an array of wl_interface references that correspond to `o` and 66 * `n` arguments in `signature`, with `NULL` placeholders for arguments with 67 * non-object types. 68 * 69 * Consider the protocol event wl_display `delete_id` that has a single `uint` 70 * argument. The wl_message is: 71 * 72 * \code 73 * { "delete_id", "u", [NULL] } 74 * \endcode 75 * 76 * Here, the message `name` is `"delete_id"`, the `signature` is `"u"`, and the 77 * argument `types` is `[NULL]`, indicating that the `uint` argument has no 78 * corresponding wl_interface since it is a primitive argument. 79 * 80 * In contrast, consider a `wl_foo` interface supporting protocol request `bar` 81 * that has existed since version 2, and has two arguments: a `uint` and an 82 * object of type `wl_baz_interface` that may be `NULL`. Such a `wl_message` 83 * might be: 84 * 85 * \code 86 * { "bar", "2u?o", [NULL, &wl_baz_interface] } 87 * \endcode 88 * 89 * Here, the message `name` is `"bar"`, and the `signature` is `"2u?o"`. Notice 90 * how the `2` indicates the protocol version, the `u` indicates the first 91 * argument type is `uint`, and the `?o` indicates that the second argument 92 * is an object that may be `NULL`. Lastly, the argument `types` array indicates 93 * that no wl_interface corresponds to the first argument, while the type 94 * `wl_baz_interface` corresponds to the second argument. 95 * 96 * \sa wl_argument 97 * \sa wl_interface 98 * \sa <a href="https://wayland.freedesktop.org/docs/html/ch04.html#sect-Protocol-Wire-Format">Wire Format</a> 99 */ 100 struct wl_message 101 { 102 /** Message name */ 103 const(char)* name; 104 /** Message signature */ 105 const(char)* signature; 106 /** Object argument interfaces */ 107 const(wl_interface*)* types; 108 } 109 110 /** 111 * Protocol object interface 112 * 113 * A wl_interface describes the API of a protocol object defined in the Wayland 114 * protocol specification. The protocol implementation uses a wl_interface 115 * within its marshalling machinery for encoding client requests. 116 * 117 * The `name` of a wl_interface is the name of the corresponding protocol 118 * interface, and `version` represents the version of the interface. The members 119 * `method_count` and `event_count` represent the number of `methods` (requests) 120 * and `events` in the respective wl_message members. 121 * 122 * For example, consider a protocol interface `foo`, marked as version `1`, with 123 * two requests and one event. 124 * 125 * \code 126 * <interface name="foo" version="1"> 127 * <request name="a"></request> 128 * <request name="b"></request> 129 * <event name="c"></event> 130 * </interface> 131 * \endcode 132 * 133 * Given two wl_message arrays `foo_requests` and `foo_events`, a wl_interface 134 * for `foo` might be: 135 * 136 * \code 137 * struct wl_interface foo_interface = { 138 * "foo", 1, 139 * 2, foo_requests, 140 * 1, foo_events 141 * }; 142 * \endcode 143 * 144 * \note The server side of the protocol may define interface <em>implementation 145 * types</em> that incorporate the term `interface` in their name. Take 146 * care to not confuse these server-side `struct`s with a wl_interface 147 * variable whose name also ends in `interface`. For example, while the 148 * server may define a type `struct wl_foo_interface`, the client may 149 * define a `struct wl_interface wl_foo_interface`. 150 * 151 * \sa wl_message 152 * \sa wl_proxy 153 * \sa <a href="https://wayland.freedesktop.org/docs/html/ch04.html#sect-Protocol-Interfaces">Interfaces</a> 154 * \sa <a href="https://wayland.freedesktop.org/docs/html/ch04.html#sect-Protocol-Versioning">Versioning</a> 155 */ 156 struct wl_interface 157 { 158 /** Interface name */ 159 const(char)* name; 160 /** Interface version */ 161 int version_; 162 /** Number of methods (requests) */ 163 int method_count; 164 /** Method (request) signatures */ 165 const(wl_message)* methods; 166 /** Number of events */ 167 int event_count; 168 /** Event signatures */ 169 const(wl_message)* events; 170 } 171 172 /** \class wl_list 173 * 174 * \brief Doubly-linked list 175 * 176 * On its own, an instance of `struct wl_list` represents the sentinel head of 177 * a doubly-linked list, and must be initialized using wl_list_init(). 178 * When empty, the list head's `next` and `prev` members point to the list head 179 * itself, otherwise `next` references the first element in the list, and `prev` 180 * refers to the last element in the list. 181 * 182 * Use the `struct wl_list` type to represent both the list head and the links 183 * between elements within the list. Use wl_list_empty() to determine if the 184 * list is empty in O(1). 185 * 186 * All elements in the list must be of the same type. The element type must have 187 * a `struct wl_list` member, often named `link` by convention. Prior to 188 * insertion, there is no need to initialize an element's `link` - invoking 189 * wl_list_init() on an individual list element's `struct wl_list` member is 190 * unnecessary if the very next operation is wl_list_insert(). However, a 191 * common idiom is to initialize an element's `link` prior to removal - ensure 192 * safety by invoking wl_list_init() before wl_list_remove(). 193 * 194 * Consider a list reference `struct wl_list foo_list`, an element type as 195 * `struct element`, and an element's link member as `struct wl_list link`. 196 * 197 * The following code initializes a list and adds three elements to it. 198 * 199 * \code 200 * struct wl_list foo_list; 201 * 202 * struct element { 203 * int foo; 204 * struct wl_list link; 205 * }; 206 * struct element e1, e2, e3; 207 * 208 * wl_list_init(&foo_list); 209 * wl_list_insert(&foo_list, &e1.link); // e1 is the first element 210 * wl_list_insert(&foo_list, &e2.link); // e2 is now the first element 211 * wl_list_insert(&e2.link, &e3.link); // insert e3 after e2 212 * \endcode 213 * 214 * The list now looks like <em>[e2, e3, e1]</em>. 215 * 216 * The `wl_list` API provides some iterator macros. For example, to iterate 217 * a list in ascending order: 218 * 219 * \code 220 * struct element *e; 221 * wl_list_for_each(e, foo_list, link) { 222 * do_something_with_element(e); 223 * } 224 * \endcode 225 * 226 * See the documentation of each iterator for details. 227 * \sa http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/include/linux/list.h 228 */ 229 struct wl_list 230 { 231 /** Previous list element */ 232 wl_list *prev; 233 /** Next list element */ 234 wl_list *next; 235 } 236 } 237 /** 238 * Retrieves a pointer to a containing struct, given a member name. 239 * 240 * This macro allows "conversion" from a pointer to a member to its containing 241 * struct. This is useful if you have a contained item like a wl_list, 242 * wl_listener, or wl_signal, provided via a callback or other means, and would 243 * like to retrieve the struct that contains it. 244 * 245 * To demonstrate, the following example retrieves a pointer to 246 * `example_container` given only its `destroy_listener` member: 247 * 248 * \code 249 * struct example_container { 250 * struct wl_listener destroy_listener; 251 * // other members... 252 * }; 253 * 254 * void example_container_destroy(struct wl_listener *listener, void *data) 255 * { 256 * struct example_container *ctr; 257 * 258 * ctr = wl_container_of(listener, ctr, destroy_listener); 259 * // destroy ctr... 260 * } 261 * \endcode 262 * 263 * \note `sample` need not be a valid pointer. A null or uninitialised pointer 264 * is sufficient. 265 * 266 * \param ptr Valid pointer to the contained member 267 * \param sample Pointer to a struct whose type contains \p ptr 268 * \param member Named location of \p ptr within the \p sample type 269 * 270 * \return The container for the specified pointer 271 */ 272 template wl_container_of(alias member) 273 { 274 static ParentOf!member* wl_container_of(T)(T* ptr) 275 { 276 return cast(ParentOf!member*)(cast(ptrdiff_t)(ptr)-member.offsetof); 277 } 278 } 279 280 /// 281 unittest { 282 283 struct S { 284 string foo; 285 int bar; 286 } 287 288 S s; 289 assert(wl_container_of!(S.bar)(&s.bar) == &s); 290 } 291 292 /// Returns a range that iterates over a wl_list. 293 /// The member alias and the passed list is the wl_list member in a container 294 /// struct, and the front type of the range is the container itself. 295 template wl_range(alias member) 296 { 297 static WlListRange!member wl_range(wl_list *head) 298 { 299 return WlListRange!member(head); 300 } 301 } 302 303 /// 304 unittest 305 { 306 struct Item 307 { 308 int num; 309 wl_list link; 310 311 this(int num) { this.num = num; } 312 } 313 auto i1 = Item(1); 314 auto i2 = Item(2); 315 auto i3 = Item(3); 316 317 wl_list lst; 318 wl_list_init(&lst); 319 wl_list_insert(&lst, &i1.link); 320 wl_list_insert(&lst, &i2.link); 321 wl_list_insert(&i2.link, &i3.link); 322 323 int[] forw_arr; 324 foreach(it; wl_range!(Item.link)(&lst)) { 325 forw_arr ~= it.num; 326 } 327 assert(forw_arr == [2, 3, 1]); 328 329 int[] back_arr; 330 foreach_reverse(it; wl_range!(Item.link)(&lst)) { 331 back_arr ~= it.num; 332 } 333 assert(back_arr == [1, 3, 2]); 334 } 335 336 337 338 // TODO: check if the following are needed given the wl_range functions 339 // /** 340 // * Iterates over a list. 341 // * 342 // * This macro expresses a for-each iterator for wl_list. Given a list and 343 // * wl_list link member name (often named `link` by convention), this macro 344 // * assigns each element in the list to \p pos, which can then be referenced in 345 // * a trailing code block. For example, given a wl_list of `struct message` 346 // * elements: 347 // * 348 // * \code 349 // * struct message { 350 // * char *contents; 351 // * wl_list link; 352 // * }; 353 // * 354 // * struct wl_list *message_list; 355 // * // Assume message_list now "contains" many messages 356 // * 357 // * struct message *m; 358 // * wl_list_for_each(m, message_list, link) { 359 // * do_something_with_message(m); 360 // * } 361 // * \endcode 362 // * 363 // * \param pos Cursor that each list element will be assigned to 364 // * \param head Head of the list to iterate over 365 // * \param member Name of the link member within the element struct 366 // * 367 // * \relates wl_list 368 // */ 369 // #define wl_list_for_each(pos, head, member) \ 370 // for (pos = wl_container_of((head)->next, pos, member); \ 371 // &pos->member != (head); \ 372 // pos = wl_container_of(pos->member.next, pos, member)) 373 // 374 // /** 375 // * Iterates over a list, safe against removal of the list element. 376 // * 377 // * \note Only removal of the current element, \p pos, is safe. Removing 378 // * any other element during traversal may lead to a loop malfunction. 379 // * 380 // * \sa wl_list_for_each() 381 // * 382 // * \param pos Cursor that each list element will be assigned to 383 // * \param tmp Temporary pointer of the same type as \p pos 384 // * \param head Head of the list to iterate over 385 // * \param member Name of the link member within the element struct 386 // * 387 // * \relates wl_list 388 // */ 389 // #define wl_list_for_each_safe(pos, tmp, head, member) \ 390 // for (pos = wl_container_of((head)->next, pos, member), \ 391 // tmp = wl_container_of((pos)->member.next, tmp, member); \ 392 // &pos->member != (head); \ 393 // pos = tmp, \ 394 // tmp = wl_container_of(pos->member.next, tmp, member)) 395 // 396 // /** 397 // * Iterates backwards over a list. 398 // * 399 // * \sa wl_list_for_each() 400 // * 401 // * \param pos Cursor that each list element will be assigned to 402 // * \param head Head of the list to iterate over 403 // * \param member Name of the link member within the element struct 404 // * 405 // * \relates wl_list 406 // */ 407 // #define wl_list_for_each_reverse(pos, head, member) \ 408 // for (pos = wl_container_of((head)->prev, pos, member); \ 409 // &pos->member != (head); \ 410 // pos = wl_container_of(pos->member.prev, pos, member)) 411 // 412 // /** 413 // * Iterates backwards over a list, safe against removal of the list element. 414 // * 415 // * \note Only removal of the current element, \p pos, is safe. Removing 416 // * any other element during traversal may lead to a loop malfunction. 417 // * 418 // * \sa wl_list_for_each() 419 // * 420 // * \param pos Cursor that each list element will be assigned to 421 // * \param tmp Temporary pointer of the same type as \p pos 422 // * \param head Head of the list to iterate over 423 // * \param member Name of the link member within the element struct 424 // * 425 // * \relates wl_list 426 // */ 427 // #define wl_list_for_each_reverse_safe(pos, tmp, head, member) \ 428 // for (pos = wl_container_of((head)->prev, pos, member), \ 429 // tmp = wl_container_of((pos)->member.prev, tmp, member); \ 430 // &pos->member != (head); \ 431 // pos = tmp, \ 432 // tmp = wl_container_of(pos->member.prev, tmp, member)) 433 434 435 436 /** 437 * \class wl_array 438 * 439 * Dynamic array 440 * 441 * A wl_array is a dynamic array that can only grow until released. It is 442 * intended for relatively small allocations whose size is variable or not known 443 * in advance. While construction of a wl_array does not require all elements to 444 * be of the same size, wl_array_for_each() does require all elements to have 445 * the same type and size. 446 * 447 */ 448 extern(C) 449 struct wl_array 450 { 451 /** Array size */ 452 size_t size; 453 /** Allocated space */ 454 size_t alloc; 455 /** Array data */ 456 void *data; 457 } 458 459 460 461 /// Returns a range that iterates over a wl_array. 462 template wl_range(T) 463 { 464 static WlArrayRange!T wl_range(wl_array *arr) 465 { 466 return WlArrayRange!T(arr); 467 } 468 } 469 470 /// 471 unittest 472 { 473 wl_array arr; 474 wl_array_init(&arr); 475 476 foreach(i; 0..1342) { 477 int *ptr = cast(int*)wl_array_add(&arr, int.sizeof); 478 *ptr = i*12 - 15; 479 480 } 481 482 int ind=0; 483 foreach(pi; wl_range!(int)(&arr)) { 484 assert(*pi == ind++*12-15); 485 } 486 assert(ind==1342); 487 488 wl_array_release(&arr); 489 } 490 491 492 493 // TODO: check if the following are needed given the wl_range functions 494 495 // /** 496 // * Iterates over an array. 497 // * 498 // * This macro expresses a for-each iterator for wl_array. It assigns each 499 // * element in the array to \p pos, which can then be referenced in a trailing 500 // * code block. \p pos must be a pointer to the array element type, and all 501 // * array elements must be of the same type and size. 502 // * 503 // * \param pos Cursor that each array element will be assigned to 504 // * \param array Array to iterate over 505 // * 506 // * \relates wl_array 507 // * \sa wl_list_for_each() 508 // */ 509 // #define wl_array_for_each(pos, array) \ 510 // for (pos = (array)->data; \ 511 // (const char *) pos < ((const char *) (array)->data + (array)->size); \ 512 // (pos)++) 513 514 515 /** 516 * Fixed-point number 517 * 518 * A `wl_fixed_t` is a 24.8 signed fixed-point number with a sign bit, 23 bits 519 * of integer precision and 8 bits of decimal precision. Consider `wl_fixed_t` 520 * as an opaque struct with methods that facilitate conversion to and from 521 * `double` and `int` types. 522 */ 523 alias wl_fixed_t = uint; 524 525 526 /** 527 * Converts a fixed-point number to a floating-point number. 528 * 529 * \param f Fixed-point number to convert 530 * 531 * \return Floating-point representation of the fixed-point argument 532 */ 533 double wl_fixed_to_double (wl_fixed_t f) 534 { 535 union di { 536 double d; 537 long i; 538 } 539 di u; 540 541 u.i = ((1023L + 44L) << 52) + (1L << 51) + f; 542 543 return u.d - (3L << 43); 544 } 545 546 547 /** 548 * Converts a floating-point number to a fixed-point number. 549 * 550 * \param d Floating-point number to convert 551 * 552 * \return Fixed-point representation of the floating-point argument 553 */ 554 wl_fixed_t wl_fixed_from_double(double d) 555 { 556 union di { 557 double d; 558 long i; 559 } 560 di u; 561 562 u.d = d + (3L << (51 - 8)); 563 564 return cast(wl_fixed_t)u.i; 565 } 566 567 568 569 /** 570 * Converts a fixed-point number to an integer. 571 * 572 * \param f Fixed-point number to convert 573 * 574 * \return Integer component of the fixed-point argument 575 */ 576 int wl_fixed_to_int(wl_fixed_t f) 577 { 578 return f / 256; 579 } 580 581 /** 582 * Converts an integer to a fixed-point number. 583 * 584 * \param i Integer to convert 585 * 586 * \return Fixed-point representation of the integer argument 587 */ 588 wl_fixed_t wl_fixed_from_int(int i) 589 { 590 return i * 256; 591 } 592 593 // wl_object resides in wayland-server.h, but referenced in wl_argument. 594 /// 595 extern(C) 596 struct wl_object; 597 598 /** 599 * Protocol message argument data types 600 * 601 * This union represents all of the argument types in the Wayland protocol wire 602 * format. The protocol implementation uses wl_argument within its marshalling 603 * machinery for dispatching messages between a client and a compositor. 604 * 605 * \sa wl_message 606 * \sa wl_interface 607 * \sa <a href="https://wayland.freedesktop.org/docs/html/ch04.html#sect-Protocol-wire-Format">Wire Format</a> 608 */ 609 extern(C) 610 union wl_argument 611 { 612 int i; /**< `int` */ 613 uint u; /**< `uint` */ 614 wl_fixed_t f; /**< `fixed` */ 615 const(char) *s; /**< `string` */ 616 wl_object *o; /**< `object` */ 617 uint n; /**< `new_id` */ 618 wl_array *a; /**< `array` */ 619 int h; /**< `fd` */ 620 } 621 622 extern(C) nothrow 623 { 624 /** 625 * Dispatcher function type alias 626 * 627 * A dispatcher is a function that handles the emitting of callbacks in client 628 * code. For programs directly using the C library, this is done by using 629 * libffi to call function pointers. When binding to languages other than C, 630 * dispatchers provide a way to abstract the function calling process to be 631 * friendlier to other function calling systems. 632 * 633 * A dispatcher takes five arguments: The first is the dispatcher-specific 634 * implementation associated with the target object. The second is the object 635 * upon which the callback is being invoked (either wl_proxy or wl_resource). 636 * The third and fourth arguments are the opcode and the wl_message 637 * corresponding to the callback. The final argument is an array of arguments 638 * received from the other process via the wire protocol. 639 * 640 * \param "const void *" Dispatcher-specific implementation data 641 * \param "void *" Callback invocation target (wl_proxy or `wl_resource`) 642 * \param uint32_t Callback opcode 643 * \param "const struct wl_message *" Callback message signature 644 * \param "union wl_argument *" Array of received arguments 645 * 646 * \return 0 on success, or -1 on failure 647 */ 648 alias wl_dispatcher_func_t = int function ( 649 const(void)* impl, 650 void* target, 651 uint opcode, 652 const(wl_message)* msg, 653 wl_argument* args); 654 655 /** 656 * Log function type alias 657 * 658 * The C implementation of the Wayland protocol abstracts the details of 659 * logging. Users may customize the logging behavior, with a function conforming 660 * to the `wl_log_func_t` type, via `wl_log_set_handler_client` and 661 * `wl_log_set_handler_server`. 662 * 663 * A `wl_log_func_t` must conform to the expectations of `vprintf`, and 664 * expects two arguments: a string to write and a corresponding variable 665 * argument list. While the string to write may contain format specifiers and 666 * use values in the variable argument list, the behavior of any `wl_log_func_t` 667 * depends on the implementation. 668 * 669 * \note Take care to not confuse this with `wl_protocol_logger_func_t`, which 670 * is a specific server-side logger for requests and events. 671 * 672 * \param "const char *" String to write to the log, containing optional format 673 * specifiers 674 * \param "va_list" Variable argument list 675 * 676 * \sa wl_log_set_handler_client 677 * \sa wl_log_set_handler_server 678 */ 679 alias wl_log_func_t = void function(const(char)*, va_list); 680 681 } 682 /** 683 * Return value of an iterator function 684 * 685 * \sa wl_client_for_each_resource_iterator_func_t 686 * \sa wl_client_for_each_resource 687 */ 688 extern(C) enum wl_iterator_result 689 { 690 /** Stop the iteration */ 691 WL_ITERATOR_STOP, 692 /** Continue the iteration */ 693 WL_ITERATOR_CONTINUE 694 } 695 696 697 version(WlDynamic) 698 { 699 extern(C) nothrow 700 { 701 alias da_wl_list_init = void function (wl_list* list); 702 703 alias da_wl_list_insert = void function (wl_list* list, wl_list* elm); 704 705 alias da_wl_list_remove = void function (wl_list* elm); 706 707 alias da_wl_list_length = int function (const(wl_list)* list); 708 709 alias da_wl_list_empty = int function (const(wl_list)* list); 710 711 alias da_wl_list_insert_list = void function (wl_list* list, wl_list* other); 712 713 alias da_wl_array_init = void function (wl_array* array); 714 715 alias da_wl_array_release = void function (wl_array* array); 716 717 alias da_wl_array_add = void* function (wl_array* array, size_t size); 718 719 alias da_wl_array_copy = int function (wl_array* array, wl_array* source); 720 } 721 722 __gshared 723 { 724 da_wl_list_init wl_list_init; 725 726 da_wl_list_insert wl_list_insert; 727 728 da_wl_list_remove wl_list_remove; 729 730 da_wl_list_length wl_list_length; 731 732 da_wl_list_empty wl_list_empty; 733 734 da_wl_list_insert_list wl_list_insert_list; 735 736 da_wl_array_init wl_array_init; 737 738 da_wl_array_release wl_array_release; 739 740 da_wl_array_add wl_array_add; 741 742 da_wl_array_copy wl_array_copy; 743 } 744 } 745 746 version(WlStatic) 747 { 748 extern(C) nothrow 749 { 750 void wl_list_init(wl_list* list); 751 752 void wl_list_insert(wl_list* list, wl_list* elm); 753 754 void wl_list_remove(wl_list* elm); 755 756 int wl_list_length(const(wl_list)* list); 757 758 int wl_list_empty(const(wl_list)* list); 759 760 void wl_list_insert_list(wl_list* list, wl_list* other); 761 762 void wl_array_init(wl_array* array); 763 764 void wl_array_release(wl_array* array); 765 766 void* wl_array_add(wl_array* array, size_t size); 767 768 int wl_array_copy(wl_array* array, wl_array* source); 769 } 770 } 771 772 773 private { 774 775 import std.range : isBidirectionalRange, isRandomAccessRange; 776 777 template Id(alias a) { alias Id = a; } 778 779 template ParentOf(alias member) 780 { 781 alias ParentOf = Id!(__traits(parent, member)); 782 } 783 784 struct WlListRange(alias member) 785 { 786 wl_list *head; 787 wl_list *fpos; 788 wl_list *bpos; 789 790 alias ElType = ParentOf!member; 791 792 this(wl_list *head) 793 { 794 this.head = head; 795 fpos = head.next; 796 bpos = head.prev; 797 } 798 799 // input 800 801 @property bool empty() const { 802 return fpos == head || bpos == head; 803 } 804 805 @property ElType *front() { 806 return wl_container_of!member(fpos); 807 } 808 809 void popFront() { 810 fpos = fpos.next; 811 } 812 813 // forward 814 815 @property WlListRange!member save() { 816 return this; 817 } 818 819 // bidirectional 820 821 @property ElType *back() { 822 return wl_container_of!member(bpos); 823 } 824 825 void popBack() { 826 bpos = bpos.prev; 827 } 828 } 829 830 831 struct Item 832 { 833 int num; 834 wl_list link; 835 836 this(int num) { this.num = num; } 837 } 838 839 static assert(isBidirectionalRange!(WlListRange!(Item.link))); 840 841 842 struct WlArrayRange(T) 843 { 844 wl_array *arr; 845 size_t fpos; 846 size_t bpos; 847 848 this (wl_array *arr) 849 { 850 assert(arr.size % T.sizeof == 0); 851 this.arr = arr; 852 fpos = 0; 853 bpos = arr.size / T.sizeof; 854 } 855 856 // input 857 858 @property bool empty() const { 859 return fpos == bpos; 860 } 861 862 @property inout(T)* front() inout { 863 return cast(inout(T)*)(arr.data + fpos*T.sizeof); 864 } 865 866 void popFront() { 867 ++fpos; 868 } 869 870 871 // forward 872 873 @property WlArrayRange!T save() { 874 return this; 875 } 876 877 878 // bidirectional 879 880 @property inout(T)* back() inout { 881 return cast(inout(T)*)(arr.data + bpos*T.sizeof); 882 } 883 884 void popBack() { 885 --bpos; 886 } 887 888 889 // random access 890 891 @property size_t length() const { 892 return bpos - fpos; 893 } 894 895 inout(T)* opIndex(size_t n) inout { 896 return cast(inout(T)*)(arr.data + (fpos+n)*T.sizeof); 897 } 898 899 } 900 901 static assert(isRandomAccessRange!(WlArrayRange!int)); 902 903 }