diff options
author | Simon Ser <contact@emersion.fr> | 2022-09-17 10:53:56 +0200 |
---|---|---|
committer | Simon Ser <contact@emersion.fr> | 2024-04-23 09:17:02 +0000 |
commit | b258d5f36137088e5cb5ae097db7964290da7d55 (patch) | |
tree | 2f59d6061156e64e8c5797942fe4818ab69529be | |
parent | 5eeaac6e1114fddeb36682ef1eead967c06e9b02 (diff) |
scanner: add validators for enums
Right now compositors need to manually check that enum values sent
by the client are valid. In particular:
- Check that the value sent by the client is not outside of the enum.
- Check that the version of the enum entry is consistent with the
object version.
Automatically generate validator functions to perform these tasks.
Signed-off-by: Simon Ser <contact@emersion.fr>
Closes: https://gitlab.freedesktop.org/wayland/wayland/-/issues/104
-rw-r--r-- | src/scanner.c | 36 | ||||
-rw-r--r-- | tests/data/empty-code.c | 1 | ||||
-rw-r--r-- | tests/data/example-code.c | 1 | ||||
-rw-r--r-- | tests/data/example-server.h | 588 | ||||
-rw-r--r-- | tests/data/small-client-core.h | 9 | ||||
-rw-r--r-- | tests/data/small-client.h | 9 | ||||
-rw-r--r-- | tests/data/small-code-core.c | 1 | ||||
-rw-r--r-- | tests/data/small-code.c | 1 | ||||
-rw-r--r-- | tests/data/small-private-code.c | 1 | ||||
-rw-r--r-- | tests/data/small-server-core.h | 31 | ||||
-rw-r--r-- | tests/data/small-server.h | 31 | ||||
-rw-r--r-- | tests/data/small.xml | 1 | ||||
-rw-r--r-- | tests/enum-validator-test.c | 13 | ||||
-rw-r--r-- | tests/meson.build | 1 |
14 files changed, 720 insertions, 4 deletions
diff --git a/src/scanner.c b/src/scanner.c index 3257cb6..3f528f3 100644 --- a/src/scanner.c +++ b/src/scanner.c @@ -1344,7 +1344,7 @@ emit_event_wrappers(struct wl_list *message_list, struct interface *interface) } static void -emit_enumerations(struct interface *interface) +emit_enumerations(struct interface *interface, bool with_validators) { struct enumeration *e; struct entry *entry; @@ -1401,6 +1401,33 @@ emit_enumerations(struct interface *interface) } + if (with_validators) { + printf("/**\n" + " * @ingroup iface_%s\n" + " * Validate a %s %s value.\n" + " *\n" + " * @return true on success, false on error.\n" + " * @ref %s_%s\n" + " */\n" + "static inline bool\n" + "%s_%s_is_valid(uint32_t value, uint32_t version) {\n" + " switch (value) {\n", + interface->name, interface->name, e->name, + interface->name, e->name, + interface->name, e->name); + wl_list_for_each(entry, &e->entry_list, link) { + printf(" case %s%s_%s_%s:\n" + " return version >= %d;\n", + entry->value[0] == '-' ? "(uint32_t)" : "", + interface->uppercase_name, e->uppercase_name, + entry->uppercase_name, entry->since); + } + printf(" default:\n" + " return false;\n" + " }\n" + "}\n"); + } + printf("#endif /* %s_%s_ENUM */\n\n", interface->uppercase_name, e->uppercase_name); } @@ -1677,7 +1704,7 @@ emit_header(struct protocol *protocol, enum side side) wl_list_for_each_safe(i, i_next, &protocol->interface_list, link) { - emit_enumerations(i); + emit_enumerations(i, side == SERVER); if (side == SERVER) { emit_structs(&i->request_list, i, side); @@ -1720,7 +1747,7 @@ emit_enum_header(struct protocol *protocol) protocol->uppercase_name); wl_list_for_each_safe(i, i_next, &protocol->interface_list, link) { - emit_enumerations(i); + emit_enumerations(i, false); free_interface(i); } @@ -1849,7 +1876,8 @@ emit_code(struct protocol *protocol, enum visibility vis) if (protocol->copyright) format_text_to_comment(protocol->copyright, true); - printf("#include <stdlib.h>\n" + printf("#include <stdbool.h>\n" + "#include <stdlib.h>\n" "#include <stdint.h>\n" "#include \"wayland-util.h\"\n\n"); diff --git a/tests/data/empty-code.c b/tests/data/empty-code.c index 6f0f619..67382d2 100644 --- a/tests/data/empty-code.c +++ b/tests/data/empty-code.c @@ -1,5 +1,6 @@ /* SCANNER TEST */ +#include <stdbool.h> #include <stdlib.h> #include <stdint.h> #include "wayland-util.h" diff --git a/tests/data/example-code.c b/tests/data/example-code.c index 2055c88..37feed7 100644 --- a/tests/data/example-code.c +++ b/tests/data/example-code.c @@ -27,6 +27,7 @@ * SOFTWARE. */ +#include <stdbool.h> #include <stdlib.h> #include <stdint.h> #include "wayland-util.h" diff --git a/tests/data/example-server.h b/tests/data/example-server.h index 7cfa4e7..b0d9226 100644 --- a/tests/data/example-server.h +++ b/tests/data/example-server.h @@ -901,6 +901,26 @@ enum wl_display_error { */ WL_DISPLAY_ERROR_NO_MEMORY = 2, }; +/** + * @ingroup iface_wl_display + * Validate a wl_display error value. + * + * @return true on success, false on error. + * @ref wl_display_error + */ +static inline bool +wl_display_error_is_valid(uint32_t value, uint32_t version) { + switch (value) { + case WL_DISPLAY_ERROR_INVALID_OBJECT: + return version >= 1; + case WL_DISPLAY_ERROR_INVALID_METHOD: + return version >= 1; + case WL_DISPLAY_ERROR_NO_MEMORY: + return version >= 1; + default: + return false; + } +} #endif /* WL_DISPLAY_ERROR_ENUM */ /** @@ -1174,6 +1194,26 @@ enum wl_shm_error { */ WL_SHM_ERROR_INVALID_FD = 2, }; +/** + * @ingroup iface_wl_shm + * Validate a wl_shm error value. + * + * @return true on success, false on error. + * @ref wl_shm_error + */ +static inline bool +wl_shm_error_is_valid(uint32_t value, uint32_t version) { + switch (value) { + case WL_SHM_ERROR_INVALID_FORMAT: + return version >= 1; + case WL_SHM_ERROR_INVALID_STRIDE: + return version >= 1; + case WL_SHM_ERROR_INVALID_FD: + return version >= 1; + default: + return false; + } +} #endif /* WL_SHM_ERROR_ENUM */ #ifndef WL_SHM_FORMAT_ENUM @@ -1426,6 +1466,136 @@ enum wl_shm_format { */ WL_SHM_FORMAT_YVU444 = 0x34325659, }; +/** + * @ingroup iface_wl_shm + * Validate a wl_shm format value. + * + * @return true on success, false on error. + * @ref wl_shm_format + */ +static inline bool +wl_shm_format_is_valid(uint32_t value, uint32_t version) { + switch (value) { + case WL_SHM_FORMAT_ARGB8888: + return version >= 1; + case WL_SHM_FORMAT_XRGB8888: + return version >= 1; + case WL_SHM_FORMAT_C8: + return version >= 1; + case WL_SHM_FORMAT_RGB332: + return version >= 1; + case WL_SHM_FORMAT_BGR233: + return version >= 1; + case WL_SHM_FORMAT_XRGB4444: + return version >= 1; + case WL_SHM_FORMAT_XBGR4444: + return version >= 1; + case WL_SHM_FORMAT_RGBX4444: + return version >= 1; + case WL_SHM_FORMAT_BGRX4444: + return version >= 1; + case WL_SHM_FORMAT_ARGB4444: + return version >= 1; + case WL_SHM_FORMAT_ABGR4444: + return version >= 1; + case WL_SHM_FORMAT_RGBA4444: + return version >= 1; + case WL_SHM_FORMAT_BGRA4444: + return version >= 1; + case WL_SHM_FORMAT_XRGB1555: + return version >= 1; + case WL_SHM_FORMAT_XBGR1555: + return version >= 1; + case WL_SHM_FORMAT_RGBX5551: + return version >= 1; + case WL_SHM_FORMAT_BGRX5551: + return version >= 1; + case WL_SHM_FORMAT_ARGB1555: + return version >= 1; + case WL_SHM_FORMAT_ABGR1555: + return version >= 1; + case WL_SHM_FORMAT_RGBA5551: + return version >= 1; + case WL_SHM_FORMAT_BGRA5551: + return version >= 1; + case WL_SHM_FORMAT_RGB565: + return version >= 1; + case WL_SHM_FORMAT_BGR565: + return version >= 1; + case WL_SHM_FORMAT_RGB888: + return version >= 1; + case WL_SHM_FORMAT_BGR888: + return version >= 1; + case WL_SHM_FORMAT_XBGR8888: + return version >= 1; + case WL_SHM_FORMAT_RGBX8888: + return version >= 1; + case WL_SHM_FORMAT_BGRX8888: + return version >= 1; + case WL_SHM_FORMAT_ABGR8888: + return version >= 1; + case WL_SHM_FORMAT_RGBA8888: + return version >= 1; + case WL_SHM_FORMAT_BGRA8888: + return version >= 1; + case WL_SHM_FORMAT_XRGB2101010: + return version >= 1; + case WL_SHM_FORMAT_XBGR2101010: + return version >= 1; + case WL_SHM_FORMAT_RGBX1010102: + return version >= 1; + case WL_SHM_FORMAT_BGRX1010102: + return version >= 1; + case WL_SHM_FORMAT_ARGB2101010: + return version >= 1; + case WL_SHM_FORMAT_ABGR2101010: + return version >= 1; + case WL_SHM_FORMAT_RGBA1010102: + return version >= 1; + case WL_SHM_FORMAT_BGRA1010102: + return version >= 1; + case WL_SHM_FORMAT_YUYV: + return version >= 1; + case WL_SHM_FORMAT_YVYU: + return version >= 1; + case WL_SHM_FORMAT_UYVY: + return version >= 1; + case WL_SHM_FORMAT_VYUY: + return version >= 1; + case WL_SHM_FORMAT_AYUV: + return version >= 1; + case WL_SHM_FORMAT_NV12: + return version >= 1; + case WL_SHM_FORMAT_NV21: + return version >= 1; + case WL_SHM_FORMAT_NV16: + return version >= 1; + case WL_SHM_FORMAT_NV61: + return version >= 1; + case WL_SHM_FORMAT_YUV410: + return version >= 1; + case WL_SHM_FORMAT_YVU410: + return version >= 1; + case WL_SHM_FORMAT_YUV411: + return version >= 1; + case WL_SHM_FORMAT_YVU411: + return version >= 1; + case WL_SHM_FORMAT_YUV420: + return version >= 1; + case WL_SHM_FORMAT_YVU420: + return version >= 1; + case WL_SHM_FORMAT_YUV422: + return version >= 1; + case WL_SHM_FORMAT_YVU422: + return version >= 1; + case WL_SHM_FORMAT_YUV444: + return version >= 1; + case WL_SHM_FORMAT_YVU444: + return version >= 1; + default: + return false; + } +} #endif /* WL_SHM_FORMAT_ENUM */ /** @@ -1536,6 +1706,28 @@ enum wl_data_offer_error { */ WL_DATA_OFFER_ERROR_INVALID_OFFER = 3, }; +/** + * @ingroup iface_wl_data_offer + * Validate a wl_data_offer error value. + * + * @return true on success, false on error. + * @ref wl_data_offer_error + */ +static inline bool +wl_data_offer_error_is_valid(uint32_t value, uint32_t version) { + switch (value) { + case WL_DATA_OFFER_ERROR_INVALID_FINISH: + return version >= 1; + case WL_DATA_OFFER_ERROR_INVALID_ACTION_MASK: + return version >= 1; + case WL_DATA_OFFER_ERROR_INVALID_ACTION: + return version >= 1; + case WL_DATA_OFFER_ERROR_INVALID_OFFER: + return version >= 1; + default: + return false; + } +} #endif /* WL_DATA_OFFER_ERROR_ENUM */ /** @@ -1748,6 +1940,24 @@ enum wl_data_source_error { */ WL_DATA_SOURCE_ERROR_INVALID_SOURCE = 1, }; +/** + * @ingroup iface_wl_data_source + * Validate a wl_data_source error value. + * + * @return true on success, false on error. + * @ref wl_data_source_error + */ +static inline bool +wl_data_source_error_is_valid(uint32_t value, uint32_t version) { + switch (value) { + case WL_DATA_SOURCE_ERROR_INVALID_ACTION_MASK: + return version >= 1; + case WL_DATA_SOURCE_ERROR_INVALID_SOURCE: + return version >= 1; + default: + return false; + } +} #endif /* WL_DATA_SOURCE_ERROR_ENUM */ /** @@ -1920,6 +2130,22 @@ enum wl_data_device_error { */ WL_DATA_DEVICE_ERROR_ROLE = 0, }; +/** + * @ingroup iface_wl_data_device + * Validate a wl_data_device error value. + * + * @return true on success, false on error. + * @ref wl_data_device_error + */ +static inline bool +wl_data_device_error_is_valid(uint32_t value, uint32_t version) { + switch (value) { + case WL_DATA_DEVICE_ERROR_ROLE: + return version >= 1; + default: + return false; + } +} #endif /* WL_DATA_DEVICE_ERROR_ENUM */ /** @@ -2161,6 +2387,28 @@ enum wl_data_device_manager_dnd_action { */ WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK = 4, }; +/** + * @ingroup iface_wl_data_device_manager + * Validate a wl_data_device_manager dnd_action value. + * + * @return true on success, false on error. + * @ref wl_data_device_manager_dnd_action + */ +static inline bool +wl_data_device_manager_dnd_action_is_valid(uint32_t value, uint32_t version) { + switch (value) { + case WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE: + return version >= 1; + case WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY: + return version >= 1; + case WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE: + return version >= 1; + case WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK: + return version >= 1; + default: + return false; + } +} #endif /* WL_DATA_DEVICE_MANAGER_DND_ACTION_ENUM */ /** @@ -2208,6 +2456,22 @@ enum wl_shell_error { */ WL_SHELL_ERROR_ROLE = 0, }; +/** + * @ingroup iface_wl_shell + * Validate a wl_shell error value. + * + * @return true on success, false on error. + * @ref wl_shell_error + */ +static inline bool +wl_shell_error_is_valid(uint32_t value, uint32_t version) { + switch (value) { + case WL_SHELL_ERROR_ROLE: + return version >= 1; + default: + return false; + } +} #endif /* WL_SHELL_ERROR_ENUM */ /** @@ -2287,6 +2551,38 @@ enum wl_shell_surface_resize { */ WL_SHELL_SURFACE_RESIZE_BOTTOM_RIGHT = 10, }; +/** + * @ingroup iface_wl_shell_surface + * Validate a wl_shell_surface resize value. + * + * @return true on success, false on error. + * @ref wl_shell_surface_resize + */ +static inline bool +wl_shell_surface_resize_is_valid(uint32_t value, uint32_t version) { + switch (value) { + case WL_SHELL_SURFACE_RESIZE_NONE: + return version >= 1; + case WL_SHELL_SURFACE_RESIZE_TOP: + return version >= 1; + case WL_SHELL_SURFACE_RESIZE_BOTTOM: + return version >= 1; + case WL_SHELL_SURFACE_RESIZE_LEFT: + return version >= 1; + case WL_SHELL_SURFACE_RESIZE_TOP_LEFT: + return version >= 1; + case WL_SHELL_SURFACE_RESIZE_BOTTOM_LEFT: + return version >= 1; + case WL_SHELL_SURFACE_RESIZE_RIGHT: + return version >= 1; + case WL_SHELL_SURFACE_RESIZE_TOP_RIGHT: + return version >= 1; + case WL_SHELL_SURFACE_RESIZE_BOTTOM_RIGHT: + return version >= 1; + default: + return false; + } +} #endif /* WL_SHELL_SURFACE_RESIZE_ENUM */ #ifndef WL_SHELL_SURFACE_TRANSIENT_ENUM @@ -2304,6 +2600,22 @@ enum wl_shell_surface_transient { */ WL_SHELL_SURFACE_TRANSIENT_INACTIVE = 0x1, }; +/** + * @ingroup iface_wl_shell_surface + * Validate a wl_shell_surface transient value. + * + * @return true on success, false on error. + * @ref wl_shell_surface_transient + */ +static inline bool +wl_shell_surface_transient_is_valid(uint32_t value, uint32_t version) { + switch (value) { + case WL_SHELL_SURFACE_TRANSIENT_INACTIVE: + return version >= 1; + default: + return false; + } +} #endif /* WL_SHELL_SURFACE_TRANSIENT_ENUM */ #ifndef WL_SHELL_SURFACE_FULLSCREEN_METHOD_ENUM @@ -2334,6 +2646,28 @@ enum wl_shell_surface_fullscreen_method { */ WL_SHELL_SURFACE_FULLSCREEN_METHOD_FILL = 3, }; +/** + * @ingroup iface_wl_shell_surface + * Validate a wl_shell_surface fullscreen_method value. + * + * @return true on success, false on error. + * @ref wl_shell_surface_fullscreen_method + */ +static inline bool +wl_shell_surface_fullscreen_method_is_valid(uint32_t value, uint32_t version) { + switch (value) { + case WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT: + return version >= 1; + case WL_SHELL_SURFACE_FULLSCREEN_METHOD_SCALE: + return version >= 1; + case WL_SHELL_SURFACE_FULLSCREEN_METHOD_DRIVER: + return version >= 1; + case WL_SHELL_SURFACE_FULLSCREEN_METHOD_FILL: + return version >= 1; + default: + return false; + } +} #endif /* WL_SHELL_SURFACE_FULLSCREEN_METHOD_ENUM */ /** @@ -2666,6 +3000,24 @@ enum wl_surface_error { */ WL_SURFACE_ERROR_INVALID_TRANSFORM = 1, }; +/** + * @ingroup iface_wl_surface + * Validate a wl_surface error value. + * + * @return true on success, false on error. + * @ref wl_surface_error + */ +static inline bool +wl_surface_error_is_valid(uint32_t value, uint32_t version) { + switch (value) { + case WL_SURFACE_ERROR_INVALID_SCALE: + return version >= 1; + case WL_SURFACE_ERROR_INVALID_TRANSFORM: + return version >= 1; + default: + return false; + } +} #endif /* WL_SURFACE_ERROR_ENUM */ /** @@ -3125,6 +3477,26 @@ enum wl_seat_capability { */ WL_SEAT_CAPABILITY_TOUCH = 4, }; +/** + * @ingroup iface_wl_seat + * Validate a wl_seat capability value. + * + * @return true on success, false on error. + * @ref wl_seat_capability + */ +static inline bool +wl_seat_capability_is_valid(uint32_t value, uint32_t version) { + switch (value) { + case WL_SEAT_CAPABILITY_POINTER: + return version >= 1; + case WL_SEAT_CAPABILITY_KEYBOARD: + return version >= 1; + case WL_SEAT_CAPABILITY_TOUCH: + return version >= 1; + default: + return false; + } +} #endif /* WL_SEAT_CAPABILITY_ENUM */ /** @@ -3249,6 +3621,22 @@ enum wl_pointer_error { */ WL_POINTER_ERROR_ROLE = 0, }; +/** + * @ingroup iface_wl_pointer + * Validate a wl_pointer error value. + * + * @return true on success, false on error. + * @ref wl_pointer_error + */ +static inline bool +wl_pointer_error_is_valid(uint32_t value, uint32_t version) { + switch (value) { + case WL_POINTER_ERROR_ROLE: + return version >= 1; + default: + return false; + } +} #endif /* WL_POINTER_ERROR_ENUM */ #ifndef WL_POINTER_BUTTON_STATE_ENUM @@ -3270,6 +3658,24 @@ enum wl_pointer_button_state { */ WL_POINTER_BUTTON_STATE_PRESSED = 1, }; +/** + * @ingroup iface_wl_pointer + * Validate a wl_pointer button_state value. + * + * @return true on success, false on error. + * @ref wl_pointer_button_state + */ +static inline bool +wl_pointer_button_state_is_valid(uint32_t value, uint32_t version) { + switch (value) { + case WL_POINTER_BUTTON_STATE_RELEASED: + return version >= 1; + case WL_POINTER_BUTTON_STATE_PRESSED: + return version >= 1; + default: + return false; + } +} #endif /* WL_POINTER_BUTTON_STATE_ENUM */ #ifndef WL_POINTER_AXIS_ENUM @@ -3290,6 +3696,24 @@ enum wl_pointer_axis { */ WL_POINTER_AXIS_HORIZONTAL_SCROLL = 1, }; +/** + * @ingroup iface_wl_pointer + * Validate a wl_pointer axis value. + * + * @return true on success, false on error. + * @ref wl_pointer_axis + */ +static inline bool +wl_pointer_axis_is_valid(uint32_t value, uint32_t version) { + switch (value) { + case WL_POINTER_AXIS_VERTICAL_SCROLL: + return version >= 1; + case WL_POINTER_AXIS_HORIZONTAL_SCROLL: + return version >= 1; + default: + return false; + } +} #endif /* WL_POINTER_AXIS_ENUM */ #ifndef WL_POINTER_AXIS_SOURCE_ENUM @@ -3338,6 +3762,28 @@ enum wl_pointer_axis_source { * @ingroup iface_wl_pointer */ #define WL_POINTER_AXIS_SOURCE_WHEEL_TILT_SINCE_VERSION 6 +/** + * @ingroup iface_wl_pointer + * Validate a wl_pointer axis_source value. + * + * @return true on success, false on error. + * @ref wl_pointer_axis_source + */ +static inline bool +wl_pointer_axis_source_is_valid(uint32_t value, uint32_t version) { + switch (value) { + case WL_POINTER_AXIS_SOURCE_WHEEL: + return version >= 1; + case WL_POINTER_AXIS_SOURCE_FINGER: + return version >= 1; + case WL_POINTER_AXIS_SOURCE_CONTINUOUS: + return version >= 1; + case WL_POINTER_AXIS_SOURCE_WHEEL_TILT: + return version >= 6; + default: + return false; + } +} #endif /* WL_POINTER_AXIS_SOURCE_ENUM */ /** @@ -3599,6 +4045,24 @@ enum wl_keyboard_keymap_format { */ WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1 = 1, }; +/** + * @ingroup iface_wl_keyboard + * Validate a wl_keyboard keymap_format value. + * + * @return true on success, false on error. + * @ref wl_keyboard_keymap_format + */ +static inline bool +wl_keyboard_keymap_format_is_valid(uint32_t value, uint32_t version) { + switch (value) { + case WL_KEYBOARD_KEYMAP_FORMAT_NO_KEYMAP: + return version >= 1; + case WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1: + return version >= 1; + default: + return false; + } +} #endif /* WL_KEYBOARD_KEYMAP_FORMAT_ENUM */ #ifndef WL_KEYBOARD_KEY_STATE_ENUM @@ -3619,6 +4083,24 @@ enum wl_keyboard_key_state { */ WL_KEYBOARD_KEY_STATE_PRESSED = 1, }; +/** + * @ingroup iface_wl_keyboard + * Validate a wl_keyboard key_state value. + * + * @return true on success, false on error. + * @ref wl_keyboard_key_state + */ +static inline bool +wl_keyboard_key_state_is_valid(uint32_t value, uint32_t version) { + switch (value) { + case WL_KEYBOARD_KEY_STATE_RELEASED: + return version >= 1; + case WL_KEYBOARD_KEY_STATE_PRESSED: + return version >= 1; + default: + return false; + } +} #endif /* WL_KEYBOARD_KEY_STATE_ENUM */ /** @@ -3945,6 +4427,32 @@ enum wl_output_subpixel { */ WL_OUTPUT_SUBPIXEL_VERTICAL_BGR = 5, }; +/** + * @ingroup iface_wl_output + * Validate a wl_output subpixel value. + * + * @return true on success, false on error. + * @ref wl_output_subpixel + */ +static inline bool +wl_output_subpixel_is_valid(uint32_t value, uint32_t version) { + switch (value) { + case WL_OUTPUT_SUBPIXEL_UNKNOWN: + return version >= 1; + case WL_OUTPUT_SUBPIXEL_NONE: + return version >= 1; + case WL_OUTPUT_SUBPIXEL_HORIZONTAL_RGB: + return version >= 1; + case WL_OUTPUT_SUBPIXEL_HORIZONTAL_BGR: + return version >= 1; + case WL_OUTPUT_SUBPIXEL_VERTICAL_RGB: + return version >= 1; + case WL_OUTPUT_SUBPIXEL_VERTICAL_BGR: + return version >= 1; + default: + return false; + } +} #endif /* WL_OUTPUT_SUBPIXEL_ENUM */ #ifndef WL_OUTPUT_TRANSFORM_ENUM @@ -3999,6 +4507,36 @@ enum wl_output_transform { */ WL_OUTPUT_TRANSFORM_FLIPPED_270 = 7, }; +/** + * @ingroup iface_wl_output + * Validate a wl_output transform value. + * + * @return true on success, false on error. + * @ref wl_output_transform + */ +static inline bool +wl_output_transform_is_valid(uint32_t value, uint32_t version) { + switch (value) { + case WL_OUTPUT_TRANSFORM_NORMAL: + return version >= 1; + case WL_OUTPUT_TRANSFORM_90: + return version >= 1; + case WL_OUTPUT_TRANSFORM_180: + return version >= 1; + case WL_OUTPUT_TRANSFORM_270: + return version >= 1; + case WL_OUTPUT_TRANSFORM_FLIPPED: + return version >= 1; + case WL_OUTPUT_TRANSFORM_FLIPPED_90: + return version >= 1; + case WL_OUTPUT_TRANSFORM_FLIPPED_180: + return version >= 1; + case WL_OUTPUT_TRANSFORM_FLIPPED_270: + return version >= 1; + default: + return false; + } +} #endif /* WL_OUTPUT_TRANSFORM_ENUM */ #ifndef WL_OUTPUT_MODE_ENUM @@ -4020,6 +4558,24 @@ enum wl_output_mode { */ WL_OUTPUT_MODE_PREFERRED = 0x2, }; +/** + * @ingroup iface_wl_output + * Validate a wl_output mode value. + * + * @return true on success, false on error. + * @ref wl_output_mode + */ +static inline bool +wl_output_mode_is_valid(uint32_t value, uint32_t version) { + switch (value) { + case WL_OUTPUT_MODE_CURRENT: + return version >= 1; + case WL_OUTPUT_MODE_PREFERRED: + return version >= 1; + default: + return false; + } +} #endif /* WL_OUTPUT_MODE_ENUM */ /** @@ -4188,6 +4744,22 @@ enum wl_subcompositor_error { */ WL_SUBCOMPOSITOR_ERROR_BAD_SURFACE = 0, }; +/** + * @ingroup iface_wl_subcompositor + * Validate a wl_subcompositor error value. + * + * @return true on success, false on error. + * @ref wl_subcompositor_error + */ +static inline bool +wl_subcompositor_error_is_valid(uint32_t value, uint32_t version) { + switch (value) { + case WL_SUBCOMPOSITOR_ERROR_BAD_SURFACE: + return version >= 1; + default: + return false; + } +} #endif /* WL_SUBCOMPOSITOR_ERROR_ENUM */ /** @@ -4243,6 +4815,22 @@ enum wl_subsurface_error { */ WL_SUBSURFACE_ERROR_BAD_SURFACE = 0, }; +/** + * @ingroup iface_wl_subsurface + * Validate a wl_subsurface error value. + * + * @return true on success, false on error. + * @ref wl_subsurface_error + */ +static inline bool +wl_subsurface_error_is_valid(uint32_t value, uint32_t version) { + switch (value) { + case WL_SUBSURFACE_ERROR_BAD_SURFACE: + return version >= 1; + default: + return false; + } +} #endif /* WL_SUBSURFACE_ERROR_ENUM */ /** diff --git a/tests/data/small-client-core.h b/tests/data/small-client-core.h index 348d2dc..e5e2193 100644 --- a/tests/data/small-client-core.h +++ b/tests/data/small-client-core.h @@ -80,11 +80,20 @@ enum intf_A_foo { * @since 2 */ INTF_A_FOO_THIRD = 2, + /** + * this is a negative value + * @since 2 + */ + INTF_A_FOO_NEGATIVE = -1, }; /** * @ingroup iface_intf_A */ #define INTF_A_FOO_THIRD_SINCE_VERSION 2 +/** + * @ingroup iface_intf_A + */ +#define INTF_A_FOO_NEGATIVE_SINCE_VERSION 2 #endif /* INTF_A_FOO_ENUM */ /** diff --git a/tests/data/small-client.h b/tests/data/small-client.h index 8c6abc5..c81b70f 100644 --- a/tests/data/small-client.h +++ b/tests/data/small-client.h @@ -80,11 +80,20 @@ enum intf_A_foo { * @since 2 */ INTF_A_FOO_THIRD = 2, + /** + * this is a negative value + * @since 2 + */ + INTF_A_FOO_NEGATIVE = -1, }; /** * @ingroup iface_intf_A */ #define INTF_A_FOO_THIRD_SINCE_VERSION 2 +/** + * @ingroup iface_intf_A + */ +#define INTF_A_FOO_NEGATIVE_SINCE_VERSION 2 #endif /* INTF_A_FOO_ENUM */ /** diff --git a/tests/data/small-code-core.c b/tests/data/small-code-core.c index bd6d33d..88e8257 100644 --- a/tests/data/small-code-core.c +++ b/tests/data/small-code-core.c @@ -25,6 +25,7 @@ * SOFTWARE. */ +#include <stdbool.h> #include <stdlib.h> #include <stdint.h> #include "wayland-util.h" diff --git a/tests/data/small-code.c b/tests/data/small-code.c index bd6d33d..88e8257 100644 --- a/tests/data/small-code.c +++ b/tests/data/small-code.c @@ -25,6 +25,7 @@ * SOFTWARE. */ +#include <stdbool.h> #include <stdlib.h> #include <stdint.h> #include "wayland-util.h" diff --git a/tests/data/small-private-code.c b/tests/data/small-private-code.c index fe035ff..1679431 100644 --- a/tests/data/small-private-code.c +++ b/tests/data/small-private-code.c @@ -25,6 +25,7 @@ * SOFTWARE. */ +#include <stdbool.h> #include <stdlib.h> #include <stdint.h> #include "wayland-util.h" diff --git a/tests/data/small-server-core.h b/tests/data/small-server-core.h index f0fd1f9..ff19d67 100644 --- a/tests/data/small-server-core.h +++ b/tests/data/small-server-core.h @@ -83,11 +83,42 @@ enum intf_A_foo { * @since 2 */ INTF_A_FOO_THIRD = 2, + /** + * this is a negative value + * @since 2 + */ + INTF_A_FOO_NEGATIVE = -1, }; /** * @ingroup iface_intf_A */ #define INTF_A_FOO_THIRD_SINCE_VERSION 2 +/** + * @ingroup iface_intf_A + */ +#define INTF_A_FOO_NEGATIVE_SINCE_VERSION 2 +/** + * @ingroup iface_intf_A + * Validate a intf_A foo value. + * + * @return true on success, false on error. + * @ref intf_A_foo + */ +static inline bool +intf_A_foo_is_valid(uint32_t value, uint32_t version) { + switch (value) { + case INTF_A_FOO_FIRST: + return version >= 1; + case INTF_A_FOO_SECOND: + return version >= 1; + case INTF_A_FOO_THIRD: + return version >= 2; + case (uint32_t)INTF_A_FOO_NEGATIVE: + return version >= 2; + default: + return false; + } +} #endif /* INTF_A_FOO_ENUM */ /** diff --git a/tests/data/small-server.h b/tests/data/small-server.h index 22b8113..13fd1ed 100644 --- a/tests/data/small-server.h +++ b/tests/data/small-server.h @@ -83,11 +83,42 @@ enum intf_A_foo { * @since 2 */ INTF_A_FOO_THIRD = 2, + /** + * this is a negative value + * @since 2 + */ + INTF_A_FOO_NEGATIVE = -1, }; /** * @ingroup iface_intf_A */ #define INTF_A_FOO_THIRD_SINCE_VERSION 2 +/** + * @ingroup iface_intf_A + */ +#define INTF_A_FOO_NEGATIVE_SINCE_VERSION 2 +/** + * @ingroup iface_intf_A + * Validate a intf_A foo value. + * + * @return true on success, false on error. + * @ref intf_A_foo + */ +static inline bool +intf_A_foo_is_valid(uint32_t value, uint32_t version) { + switch (value) { + case INTF_A_FOO_FIRST: + return version >= 1; + case INTF_A_FOO_SECOND: + return version >= 1; + case INTF_A_FOO_THIRD: + return version >= 2; + case (uint32_t)INTF_A_FOO_NEGATIVE: + return version >= 2; + default: + return false; + } +} #endif /* INTF_A_FOO_ENUM */ /** diff --git a/tests/data/small.xml b/tests/data/small.xml index 832ed0e..685c891 100644 --- a/tests/data/small.xml +++ b/tests/data/small.xml @@ -53,6 +53,7 @@ <entry name="first" value="0" summary="this is the first"/> <entry name="second" value="1" summary="this is the second"/> <entry name="third" value="2" since="2" summary="this is the third"/> + <entry name="negative" value="-1" since="2" summary="this is a negative value"/> </enum> </interface> </protocol> diff --git a/tests/enum-validator-test.c b/tests/enum-validator-test.c new file mode 100644 index 0000000..92037cf --- /dev/null +++ b/tests/enum-validator-test.c @@ -0,0 +1,13 @@ +#include <assert.h> +#include "data/small-server-core.h" + +int +main(int argc, char *argv[]) { + assert(intf_A_foo_is_valid(INTF_A_FOO_FIRST, 1)); + assert(intf_A_foo_is_valid(INTF_A_FOO_FIRST, 2)); + + assert(!intf_A_foo_is_valid(INTF_A_FOO_THIRD, 1)); + assert(intf_A_foo_is_valid(INTF_A_FOO_THIRD, 2)); + + assert(intf_A_foo_is_valid(INTF_A_FOO_NEGATIVE, 2)); +} diff --git a/tests/meson.build b/tests/meson.build index 236f08c..2c22b82 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -158,6 +158,7 @@ tests = { wayland_client_protocol_h, wayland_server_protocol_h, ], + 'enum-validator-test': [], } foreach test_name, test_extra_sources: tests |