1/*
2 * Copyright © 2008 Kristian Høgsberg
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files (the
6 * "Software"), to deal in the Software without restriction, including
7 * without limitation the rights to use, copy, modify, merge, publish,
8 * distribute, sublicense, and/or sell copies of the Software, and to
9 * permit persons to whom the Software is furnished to do so, subject to
10 * the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the
13 * next paragraph) shall be included in all copies or substantial
14 * portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
20 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
21 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 * SOFTWARE.
24 */
25
26/** \file wayland-util.h
27 *
28 * \brief Utility classes, functions, and macros.
29 */
30
31#ifndef WAYLAND_UTIL_H
32#define WAYLAND_UTIL_H
33
34#include <math.h>
35#include <stddef.h>
36#include <inttypes.h>
37#include <stdarg.h>
38
39#ifdef __cplusplus
40extern "C" {
41#endif
42
43/** Visibility attribute */
44#if defined(__GNUC__) && __GNUC__ >= 4
45#define WL_EXPORT __attribute__ ((visibility("default")))
46#else
47#define WL_EXPORT
48#endif
49
50/** Deprecated attribute */
51#if defined(__GNUC__) && __GNUC__ >= 4
52#define WL_DEPRECATED __attribute__ ((deprecated))
53#else
54#define WL_DEPRECATED
55#endif
56
57/**
58 * Printf-style argument attribute
59 *
60 * \param x Ordinality of the format string argument
61 * \param y Ordinality of the argument to check against the format string
62 *
63 * \sa https://gcc.gnu.org/onlinedocs/gcc-3.2.1/gcc/Function-Attributes.html
64 */
65#if defined(__GNUC__) && __GNUC__ >= 4
66#define WL_PRINTF(x, y) __attribute__((__format__(__printf__, x, y)))
67#else
68#define WL_PRINTF(x, y)
69#endif
70
71/**
72 * Protocol message signature
73 *
74 * A wl_message describes the signature of an actual protocol message, such as a
75 * request or event, that adheres to the Wayland protocol wire format. The
76 * protocol implementation uses a wl_message within its demarshal machinery for
77 * decoding messages between a compositor and its clients. In a sense, a
78 * wl_message is to a protocol message like a class is to an object.
79 *
80 * The `name` of a wl_message is the name of the corresponding protocol message.
81 *
82 * The `signature` is an ordered list of symbols representing the data types
83 * of message arguments and, optionally, a protocol version and indicators for
84 * nullability. A leading integer in the `signature` indicates the _since_
85 * version of the protocol message. A `?` preceding a data type symbol indicates
86 * that the following argument type is nullable. While it is a protocol violation
87 * to send messages with non-nullable arguments set to `NULL`, event handlers in
88 * clients might still get called with non-nullable object arguments set to
89 * `NULL`. This can happen when the client destroyed the object being used as
90 * argument on its side and an event referencing that object was sent before the
91 * server knew about its destruction. As this race cannot be prevented, clients
92 * should - as a general rule - program their event handlers such that they can
93 * handle object arguments declared non-nullable being `NULL` gracefully.
94 *
95 * When no arguments accompany a message, `signature` is an empty string.
96 *
97 * Symbols:
98 *
99 * * `i`: int
100 * * `u`: uint
101 * * `f`: fixed
102 * * `s`: string
103 * * `o`: object
104 * * `n`: new_id
105 * * `a`: array
106 * * `h`: fd
107 * * `?`: following argument is nullable
108 *
109 * While demarshaling primitive arguments is straightforward, when demarshaling
110 * messages containing `object` or `new_id` arguments, the protocol
111 * implementation often must determine the type of the object. The `types` of a
112 * wl_message is an array of wl_interface references that correspond to `o` and
113 * `n` arguments in `signature`, with `NULL` placeholders for arguments with
114 * non-object types.
115 *
116 * Consider the protocol event wl_display `delete_id` that has a single `uint`
117 * argument. The wl_message is:
118 *
119 * \code
120 * { "delete_id", "u", [NULL] }
121 * \endcode
122 *
123 * Here, the message `name` is `"delete_id"`, the `signature` is `"u"`, and the
124 * argument `types` is `[NULL]`, indicating that the `uint` argument has no
125 * corresponding wl_interface since it is a primitive argument.
126 *
127 * In contrast, consider a `wl_foo` interface supporting protocol request `bar`
128 * that has existed since version 2, and has two arguments: a `uint` and an
129 * object of type `wl_baz_interface` that may be `NULL`. Such a `wl_message`
130 * might be:
131 *
132 * \code
133 * { "bar", "2u?o", [NULL, &wl_baz_interface] }
134 * \endcode
135 *
136 * Here, the message `name` is `"bar"`, and the `signature` is `"2u?o"`. Notice
137 * how the `2` indicates the protocol version, the `u` indicates the first
138 * argument type is `uint`, and the `?o` indicates that the second argument
139 * is an object that may be `NULL`. Lastly, the argument `types` array indicates
140 * that no wl_interface corresponds to the first argument, while the type
141 * `wl_baz_interface` corresponds to the second argument.
142 *
143 * \sa wl_argument
144 * \sa wl_interface
145 * \sa <a href="https://wayland.freedesktop.org/docs/html/ch04.html#sect-Protocol-Wire-Format">Wire Format</a>
146 */
147struct wl_message {
148 /** Message name */
149 const char *name;
150 /** Message signature */
151 const char *signature;
152 /** Object argument interfaces */
153 const struct wl_interface **types;
154};
155
156/**
157 * Protocol object interface
158 *
159 * A wl_interface describes the API of a protocol object defined in the Wayland
160 * protocol specification. The protocol implementation uses a wl_interface
161 * within its marshalling machinery for encoding client requests.
162 *
163 * The `name` of a wl_interface is the name of the corresponding protocol
164 * interface, and `version` represents the version of the interface. The members
165 * `method_count` and `event_count` represent the number of `methods` (requests)
166 * and `events` in the respective wl_message members.
167 *
168 * For example, consider a protocol interface `foo`, marked as version `1`, with
169 * two requests and one event.
170 *
171 * \code
172 * <interface name="foo" version="1">
173 * <request name="a"></request>
174 * <request name="b"></request>
175 * <event name="c"></event>
176 * </interface>
177 * \endcode
178 *
179 * Given two wl_message arrays `foo_requests` and `foo_events`, a wl_interface
180 * for `foo` might be:
181 *
182 * \code
183 * struct wl_interface foo_interface = {
184 * "foo", 1,
185 * 2, foo_requests,
186 * 1, foo_events
187 * };
188 * \endcode
189 *
190 * \note The server side of the protocol may define interface <em>implementation
191 * types</em> that incorporate the term `interface` in their name. Take
192 * care to not confuse these server-side `struct`s with a wl_interface
193 * variable whose name also ends in `interface`. For example, while the
194 * server may define a type `struct wl_foo_interface`, the client may
195 * define a `struct wl_interface wl_foo_interface`.
196 *
197 * \sa wl_message
198 * \sa wl_proxy
199 * \sa <a href="https://wayland.freedesktop.org/docs/html/ch04.html#sect-Protocol-Interfaces">Interfaces</a>
200 * \sa <a href="https://wayland.freedesktop.org/docs/html/ch04.html#sect-Protocol-Versioning">Versioning</a>
201 */
202struct wl_interface {
203 /** Interface name */
204 const char *name;
205 /** Interface version */
206 int version;
207 /** Number of methods (requests) */
208 int method_count;
209 /** Method (request) signatures */
210 const struct wl_message *methods;
211 /** Number of events */
212 int event_count;
213 /** Event signatures */
214 const struct wl_message *events;
215};
216
217/** \class wl_list
218 *
219 * \brief Doubly-linked list
220 *
221 * On its own, an instance of `struct wl_list` represents the sentinel head of
222 * a doubly-linked list, and must be initialized using wl_list_init().
223 * When empty, the list head's `next` and `prev` members point to the list head
224 * itself, otherwise `next` references the first element in the list, and `prev`
225 * refers to the last element in the list.
226 *
227 * Use the `struct wl_list` type to represent both the list head and the links
228 * between elements within the list. Use wl_list_empty() to determine if the
229 * list is empty in O(1).
230 *
231 * All elements in the list must be of the same type. The element type must have
232 * a `struct wl_list` member, often named `link` by convention. Prior to
233 * insertion, there is no need to initialize an element's `link` - invoking
234 * wl_list_init() on an individual list element's `struct wl_list` member is
235 * unnecessary if the very next operation is wl_list_insert(). However, a
236 * common idiom is to initialize an element's `link` prior to removal - ensure
237 * safety by invoking wl_list_init() before wl_list_remove().
238 *
239 * Consider a list reference `struct wl_list foo_list`, an element type as
240 * `struct element`, and an element's link member as `struct wl_list link`.
241 *
242 * The following code initializes a list and adds three elements to it.
243 *
244 * \code
245 * struct wl_list foo_list;
246 *
247 * struct element {
248 * int foo;
249 * struct wl_list link;
250 * };
251 * struct element e1, e2, e3;
252 *
253 * wl_list_init(&foo_list);
254 * wl_list_insert(&foo_list, &e1.link); // e1 is the first element
255 * wl_list_insert(&foo_list, &e2.link); // e2 is now the first element
256 * wl_list_insert(&e2.link, &e3.link); // insert e3 after e2
257 * \endcode
258 *
259 * The list now looks like <em>[e2, e3, e1]</em>.
260 *
261 * The `wl_list` API provides some iterator macros. For example, to iterate
262 * a list in ascending order:
263 *
264 * \code
265 * struct element *e;
266 * wl_list_for_each(e, foo_list, link) {
267 * do_something_with_element(e);
268 * }
269 * \endcode
270 *
271 * See the documentation of each iterator for details.
272 * \sa http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/include/linux/list.h
273 */
274struct wl_list {
275 /** Previous list element */
276 struct wl_list *prev;
277 /** Next list element */
278 struct wl_list *next;
279};
280
281/**
282 * Initializes the list.
283 *
284 * \param list List to initialize
285 *
286 * \memberof wl_list
287 */
288void
289wl_list_init(struct wl_list *list);
290
291/**
292 * Inserts an element into the list, after the element represented by \p list.
293 * When \p list is a reference to the list itself (the head), set the containing
294 * struct of \p elm as the first element in the list.
295 *
296 * \note If \p elm is already part of a list, inserting it again will lead to
297 * list corruption.
298 *
299 * \param list List element after which the new element is inserted
300 * \param elm Link of the containing struct to insert into the list
301 *
302 * \memberof wl_list
303 */
304void
305wl_list_insert(struct wl_list *list, struct wl_list *elm);
306
307/**
308 * Removes an element from the list.
309 *
310 * \note This operation leaves \p elm in an invalid state.
311 *
312 * \param elm Link of the containing struct to remove from the list
313 *
314 * \memberof wl_list
315 */
316void
317wl_list_remove(struct wl_list *elm);
318
319/**
320 * Determines the length of the list.
321 *
322 * \note This is an O(n) operation.
323 *
324 * \param list List whose length is to be determined
325 *
326 * \return Number of elements in the list
327 *
328 * \memberof wl_list
329 */
330int
331wl_list_length(const struct wl_list *list);
332
333/**
334 * Determines if the list is empty.
335 *
336 * \param list List whose emptiness is to be determined
337 *
338 * \return 1 if empty, or 0 if not empty
339 *
340 * \memberof wl_list
341 */
342int
343wl_list_empty(const struct wl_list *list);
344
345/**
346 * Inserts all of the elements of one list into another, after the element
347 * represented by \p list.
348 *
349 * \note This leaves \p other in an invalid state.
350 *
351 * \param list List element after which the other list elements will be inserted
352 * \param other List of elements to insert
353 *
354 * \memberof wl_list
355 */
356void
357wl_list_insert_list(struct wl_list *list, struct wl_list *other);
358
359/**
360 * Retrieves a pointer to a containing struct, given a member name.
361 *
362 * This macro allows "conversion" from a pointer to a member to its containing
363 * struct. This is useful if you have a contained item like a wl_list,
364 * wl_listener, or wl_signal, provided via a callback or other means, and would
365 * like to retrieve the struct that contains it.
366 *
367 * To demonstrate, the following example retrieves a pointer to
368 * `example_container` given only its `destroy_listener` member:
369 *
370 * \code
371 * struct example_container {
372 * struct wl_listener destroy_listener;
373 * // other members...
374 * };
375 *
376 * void example_container_destroy(struct wl_listener *listener, void *data)
377 * {
378 * struct example_container *ctr;
379 *
380 * ctr = wl_container_of(listener, ctr, destroy_listener);
381 * // destroy ctr...
382 * }
383 * \endcode
384 *
385 * \note `sample` need not be a valid pointer. A null or uninitialised pointer
386 * is sufficient.
387 *
388 * \param ptr Valid pointer to the contained member
389 * \param sample Pointer to a struct whose type contains \p ptr
390 * \param member Named location of \p ptr within the \p sample type
391 *
392 * \return The container for the specified pointer
393 */
394#define wl_container_of(ptr, sample, member) \
395 (__typeof__(sample))((char *)(ptr) - \
396 offsetof(__typeof__(*sample), member))
397
398/**
399 * Iterates over a list.
400 *
401 * This macro expresses a for-each iterator for wl_list. Given a list and
402 * wl_list link member name (often named `link` by convention), this macro
403 * assigns each element in the list to \p pos, which can then be referenced in
404 * a trailing code block. For example, given a wl_list of `struct message`
405 * elements:
406 *
407 * \code
408 * struct message {
409 * char *contents;
410 * wl_list link;
411 * };
412 *
413 * struct wl_list *message_list;
414 * // Assume message_list now "contains" many messages
415 *
416 * struct message *m;
417 * wl_list_for_each(m, message_list, link) {
418 * do_something_with_message(m);
419 * }
420 * \endcode
421 *
422 * \param pos Cursor that each list element will be assigned to
423 * \param head Head of the list to iterate over
424 * \param member Name of the link member within the element struct
425 *
426 * \relates wl_list
427 */
428#define wl_list_for_each(pos, head, member) \
429 for (pos = wl_container_of((head)->next, pos, member); \
430 &pos->member != (head); \
431 pos = wl_container_of(pos->member.next, pos, member))
432
433/**
434 * Iterates over a list, safe against removal of the list element.
435 *
436 * \note Only removal of the current element, \p pos, is safe. Removing
437 * any other element during traversal may lead to a loop malfunction.
438 *
439 * \sa wl_list_for_each()
440 *
441 * \param pos Cursor that each list element will be assigned to
442 * \param tmp Temporary pointer of the same type as \p pos
443 * \param head Head of the list to iterate over
444 * \param member Name of the link member within the element struct
445 *
446 * \relates wl_list
447 */
448#define wl_list_for_each_safe(pos, tmp, head, member) \
449 for (pos = wl_container_of((head)->next, pos, member), \
450 tmp = wl_container_of((pos)->member.next, tmp, member); \
451 &pos->member != (head); \
452 pos = tmp, \
453 tmp = wl_container_of(pos->member.next, tmp, member))
454
455/**
456 * Iterates backwards over a list.
457 *
458 * \sa wl_list_for_each()
459 *
460 * \param pos Cursor that each list element will be assigned to
461 * \param head Head of the list to iterate over
462 * \param member Name of the link member within the element struct
463 *
464 * \relates wl_list
465 */
466#define wl_list_for_each_reverse(pos, head, member) \
467 for (pos = wl_container_of((head)->prev, pos, member); \
468 &pos->member != (head); \
469 pos = wl_container_of(pos->member.prev, pos, member))
470
471/**
472 * Iterates backwards over a list, safe against removal of the list element.
473 *
474 * \note Only removal of the current element, \p pos, is safe. Removing
475 * any other element during traversal may lead to a loop malfunction.
476 *
477 * \sa wl_list_for_each()
478 *
479 * \param pos Cursor that each list element will be assigned to
480 * \param tmp Temporary pointer of the same type as \p pos
481 * \param head Head of the list to iterate over
482 * \param member Name of the link member within the element struct
483 *
484 * \relates wl_list
485 */
486#define wl_list_for_each_reverse_safe(pos, tmp, head, member) \
487 for (pos = wl_container_of((head)->prev, pos, member), \
488 tmp = wl_container_of((pos)->member.prev, tmp, member); \
489 &pos->member != (head); \
490 pos = tmp, \
491 tmp = wl_container_of(pos->member.prev, tmp, member))
492
493/**
494 * \class wl_array
495 *
496 * Dynamic array
497 *
498 * A wl_array is a dynamic array that can only grow until released. It is
499 * intended for relatively small allocations whose size is variable or not known
500 * in advance. While construction of a wl_array does not require all elements to
501 * be of the same size, wl_array_for_each() does require all elements to have
502 * the same type and size.
503 *
504 */
505struct wl_array {
506 /** Array size */
507 size_t size;
508 /** Allocated space */
509 size_t alloc;
510 /** Array data */
511 void *data;
512};
513
514/**
515 * Initializes the array.
516 *
517 * \param array Array to initialize
518 *
519 * \memberof wl_array
520 */
521void
522wl_array_init(struct wl_array *array);
523
524/**
525 * Releases the array data.
526 *
527 * \note Leaves the array in an invalid state.
528 *
529 * \param array Array whose data is to be released
530 *
531 * \memberof wl_array
532 */
533void
534wl_array_release(struct wl_array *array);
535
536/**
537 * Increases the size of the array by \p size bytes.
538 *
539 * \param array Array whose size is to be increased
540 * \param size Number of bytes to increase the size of the array by
541 *
542 * \return A pointer to the beginning of the newly appended space, or NULL when
543 * resizing fails.
544 *
545 * \memberof wl_array
546 */
547void *
548wl_array_add(struct wl_array *array, size_t size);
549
550/**
551 * Copies the contents of \p source to \p array.
552 *
553 * \param array Destination array to copy to
554 * \param source Source array to copy from
555 *
556 * \return 0 on success, or -1 on failure
557 *
558 * \memberof wl_array
559 */
560int
561wl_array_copy(struct wl_array *array, struct wl_array *source);
562
563/**
564 * Iterates over an array.
565 *
566 * This macro expresses a for-each iterator for wl_array. It assigns each
567 * element in the array to \p pos, which can then be referenced in a trailing
568 * code block. \p pos must be a pointer to the array element type, and all
569 * array elements must be of the same type and size.
570 *
571 * \param pos Cursor that each array element will be assigned to
572 * \param array Array to iterate over
573 *
574 * \relates wl_array
575 * \sa wl_list_for_each()
576 */
577#define wl_array_for_each(pos, array) \
578 for (pos = (array)->data; \
579 (const char *) pos < ((const char *) (array)->data + (array)->size); \
580 (pos)++)
581
582/**
583 * Fixed-point number
584 *
585 * A `wl_fixed_t` is a 24.8 signed fixed-point number with a sign bit, 23 bits
586 * of integer precision and 8 bits of decimal precision. Consider `wl_fixed_t`
587 * as an opaque struct with methods that facilitate conversion to and from
588 * `double` and `int` types.
589 */
590typedef int32_t wl_fixed_t;
591
592/**
593 * Converts a fixed-point number to a floating-point number.
594 *
595 * \param f Fixed-point number to convert
596 *
597 * \return Floating-point representation of the fixed-point argument
598 */
599static inline double
600wl_fixed_to_double(wl_fixed_t f)
601{
602 union {
603 double d;
604 int64_t i;
605 } u;
606
607 u.i = ((1023LL + 44LL) << 52) + (1LL << 51) + f;
608
609 return u.d - (3LL << 43);
610}
611
612/**
613 * Converts a floating-point number to a fixed-point number.
614 *
615 * \param d Floating-point number to convert
616 *
617 * \return Fixed-point representation of the floating-point argument
618 */
619static inline wl_fixed_t
620wl_fixed_from_double(double d)
621{
622 union {
623 double d;
624 int64_t i;
625 } u;
626
627 u.d = d + (3LL << (51 - 8));
628
629 return u.i;
630}
631
632/**
633 * Converts a fixed-point number to an integer.
634 *
635 * \param f Fixed-point number to convert
636 *
637 * \return Integer component of the fixed-point argument
638 */
639static inline int
640wl_fixed_to_int(wl_fixed_t f)
641{
642 return f / 256;
643}
644
645/**
646 * Converts an integer to a fixed-point number.
647 *
648 * \param i Integer to convert
649 *
650 * \return Fixed-point representation of the integer argument
651 */
652static inline wl_fixed_t
653wl_fixed_from_int(int i)
654{
655 return i * 256;
656}
657
658/**
659 * Protocol message argument data types
660 *
661 * This union represents all of the argument types in the Wayland protocol wire
662 * format. The protocol implementation uses wl_argument within its marshalling
663 * machinery for dispatching messages between a client and a compositor.
664 *
665 * \sa wl_message
666 * \sa wl_interface
667 * \sa <a href="https://wayland.freedesktop.org/docs/html/ch04.html#sect-Protocol-wire-Format">Wire Format</a>
668 */
669union wl_argument {
670 int32_t i; /**< `int` */
671 uint32_t u; /**< `uint` */
672 wl_fixed_t f; /**< `fixed` */
673 const char *s; /**< `string` */
674 struct wl_object *o; /**< `object` */
675 uint32_t n; /**< `new_id` */
676 struct wl_array *a; /**< `array` */
677 int32_t h; /**< `fd` */
678};
679
680/**
681 * Dispatcher function type alias
682 *
683 * A dispatcher is a function that handles the emitting of callbacks in client
684 * code. For programs directly using the C library, this is done by using
685 * libffi to call function pointers. When binding to languages other than C,
686 * dispatchers provide a way to abstract the function calling process to be
687 * friendlier to other function calling systems.
688 *
689 * A dispatcher takes five arguments: The first is the dispatcher-specific
690 * implementation associated with the target object. The second is the object
691 * upon which the callback is being invoked (either wl_proxy or wl_resource).
692 * The third and fourth arguments are the opcode and the wl_message
693 * corresponding to the callback. The final argument is an array of arguments
694 * received from the other process via the wire protocol.
695 *
696 * \param "const void *" Dispatcher-specific implementation data
697 * \param "void *" Callback invocation target (wl_proxy or `wl_resource`)
698 * \param uint32_t Callback opcode
699 * \param "const struct wl_message *" Callback message signature
700 * \param "union wl_argument *" Array of received arguments
701 *
702 * \return 0 on success, or -1 on failure
703 */
704typedef int (*wl_dispatcher_func_t)(const void *, void *, uint32_t,
705 const struct wl_message *,
706 union wl_argument *);
707
708/**
709 * Log function type alias
710 *
711 * The C implementation of the Wayland protocol abstracts the details of
712 * logging. Users may customize the logging behavior, with a function conforming
713 * to the `wl_log_func_t` type, via `wl_log_set_handler_client` and
714 * `wl_log_set_handler_server`.
715 *
716 * A `wl_log_func_t` must conform to the expectations of `vprintf`, and
717 * expects two arguments: a string to write and a corresponding variable
718 * argument list. While the string to write may contain format specifiers and
719 * use values in the variable argument list, the behavior of any `wl_log_func_t`
720 * depends on the implementation.
721 *
722 * \note Take care to not confuse this with `wl_protocol_logger_func_t`, which
723 * is a specific server-side logger for requests and events.
724 *
725 * \param "const char *" String to write to the log, containing optional format
726 * specifiers
727 * \param "va_list" Variable argument list
728 *
729 * \sa wl_log_set_handler_client
730 * \sa wl_log_set_handler_server
731 */
732typedef void (*wl_log_func_t)(const char *, va_list) WL_PRINTF(1, 0);
733
734/**
735 * Return value of an iterator function
736 *
737 * \sa wl_client_for_each_resource_iterator_func_t
738 * \sa wl_client_for_each_resource
739 */
740enum wl_iterator_result {
741 /** Stop the iteration */
742 WL_ITERATOR_STOP,
743 /** Continue the iteration */
744 WL_ITERATOR_CONTINUE
745};
746
747#ifdef __cplusplus
748}
749#endif
750
751#endif
752