From 4ed12c46dec9a3055e009c5ecd6cba5c258ce642 Mon Sep 17 00:00:00 2001 From: Uli Schlachter Date: Sat, 4 Apr 2015 10:59:12 +0200 Subject: Don't check codes to be in range, but find "best match" If some new events are added to an extension, older implementations register a smaller portion of the event number space than this library possible knows. So we cannot just look for some extension that has some code "in range", but we need to find the best one (with the largest base). Signed-off-by: Uli Schlachter --- src/xcb_errors.c | 56 ++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 40 insertions(+), 16 deletions(-) diff --git a/src/xcb_errors.c b/src/xcb_errors.c index 7594c31..25b42d4 100644 --- a/src/xcb_errors.c +++ b/src/xcb_errors.c @@ -28,8 +28,6 @@ #include #include -#define IS_IN_RANGE(value, begin, length) ((value) >= (begin) && (value) < (begin) + (length)) - struct extension_info_t { struct extension_info_t *next; struct static_extension_info_t static_info; @@ -151,29 +149,55 @@ const char *xcb_errors_get_name_for_minor_code(xcb_errors_context_t *ctx, const char *xcb_errors_get_name_for_event(xcb_errors_context_t *ctx, uint8_t event_code) { - struct extension_info_t *info = ctx->extensions; - - while (info && (info->first_event == 0 - || !IS_IN_RANGE(event_code, info->first_event, info->static_info.num_events))) - info = info->next; + struct extension_info_t *best = NULL; + struct extension_info_t *next = ctx->extensions; + + /* Find the extension with the largest first_event <= event_code. Thanks + * to this we do the right thing if the server only supports an older + * version of some extension which had less events. + */ + while (next) { + struct extension_info_t *current = next; + next = next->next; + + if (current->first_event > event_code) + continue; + if (best != NULL && best->first_event > current->first_event) + continue; + best = current; + } - if (info == NULL) + if (best == NULL || best->first_event == 0) + /* Nothing found */ return get_strings_entry(xproto_info.strings_events, event_code); - return get_strings_entry(info->static_info.strings_events, event_code - info->first_event); + return get_strings_entry(best->static_info.strings_events, event_code - best->first_event); } const char *xcb_errors_get_name_for_error(xcb_errors_context_t *ctx, uint8_t error_code) { - struct extension_info_t *info = ctx->extensions; - - while (info && (info->first_error == 0 - || !IS_IN_RANGE(error_code, info->first_error, info->static_info.num_errors))) - info = info->next; + struct extension_info_t *best = NULL; + struct extension_info_t *next = ctx->extensions; + + /* Find the extension with the largest first_error <= error_code. Thanks + * to this we do the right thing if the server only supports an older + * version of some extension which had less events. + */ + while (next) { + struct extension_info_t *current = next; + next = next->next; + + if (current->first_error > error_code) + continue; + if (best != NULL && best->first_error > current->first_error) + continue; + best = current; + } - if (info == NULL) + if (best == NULL || best->first_error == 0) + /* Nothing found */ return get_strings_entry(xproto_info.strings_errors, error_code); - return get_strings_entry(info->static_info.strings_errors, error_code - info->first_error); + return get_strings_entry(best->static_info.strings_errors, error_code - best->first_error); } -- cgit v1.2.3