From 5fda1e05dc06b11055463d89719b7ce7381b4b1b Mon Sep 17 00:00:00 2001 From: Mahmoud Al-Qudsi Date: Mon, 8 Feb 2021 13:48:23 -0600 Subject: [PATCH] Statically assert the sort order of input_function_metadata_t --- src/common.h | 37 +++++++++++++++++++++++++++++++++++++ src/input.cpp | 3 ++- 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/src/common.h b/src/common.h index eaae8fd07..0a8728e78 100644 --- a/src/common.h +++ b/src/common.h @@ -716,4 +716,41 @@ struct cleanup_t { bool is_console_session(); +/// Compile-time agnostic-size strcmp/wcscmp implementation. Unicode-unaware. +template +constexpr ssize_t const_strcmp(const T *lhs, const T *rhs) { + return (*lhs == *rhs) ? (*lhs == 0 ? 0 : const_strcmp(lhs + 1, rhs + 1)) + : (*lhs > *rhs ? 1 : -1); +} +static_assert(const_strcmp("", "a") < 0, "const_strcmp failure"); +static_assert(const_strcmp("a", "a") == 0, "const_strcmp failure"); +static_assert(const_strcmp("a", "") > 0, "const_strcmp failure"); +static_assert(const_strcmp("aa", "a") > 0, "const_strcmp failure"); +static_assert(const_strcmp("a", "aa") < 0, "const_strcmp failure"); +static_assert(const_strcmp("b", "aa") > 0, "const_strcmp failure"); + +/// Compile-time agnostic-size strlen/wcslen implementation. Unicode-unaware. +template +constexpr ssize_t const_strlen(const T *str) { + return *str == static_cast(0) ? 0 : 1 + const_strlen(str + 1); +} +static_assert(const_strlen("") == 0, "const_strlen failure"); +static_assert(const_strlen("hello") == 5, "const_strlen failure"); + +/// Compile-time assertion of alphabetical sort of array `array`, by specified +/// parameter `accessor`. This is only a macro because constexpr lambdas (to +/// specify the accessor for the sort key) are C++17 and up. +#define ASSERT_SORT_ORDER(array, accessor) \ + struct verify_ ## array ## _sort_t { \ + template \ + constexpr static bool validate(T(&vals)[N], size_t idx = 0) { \ + return (idx == (((sizeof(array) / sizeof(vals[0]))) - 1)) \ + ? true \ + : const_strcmp(vals[idx] accessor, vals[idx + 1] accessor) <= 0 && \ + verify_ ## array ## _sort_t::validate(vals, idx + 1); \ + } \ +}; \ +static_assert(verify_ ## array ## _sort_t::validate(array), \ + #array " members not in asciibetical order!"); + #endif // FISH_COMMON_H diff --git a/src/input.cpp b/src/input.cpp index 5581ae30e..25e731dc7 100644 --- a/src/input.cpp +++ b/src/input.cpp @@ -86,7 +86,7 @@ struct input_function_metadata_t { /// A static mapping of all readline commands as strings to their readline_cmd_t equivalent. /// Keep this list sorted alphabetically! -static const input_function_metadata_t input_function_metadata[] = { +static constexpr const input_function_metadata_t input_function_metadata[] = { // NULL makes it unusable - this is specially inserted when we detect mouse input {L"", readline_cmd_t::disable_mouse_tracking}, {L"accept-autosuggestion", readline_cmd_t::accept_autosuggestion}, @@ -165,6 +165,7 @@ static const input_function_metadata_t input_function_metadata[] = { {L"yank-pop", readline_cmd_t::yank_pop}, }; +ASSERT_SORT_ORDER(input_function_metadata, .name); static_assert(sizeof(input_function_metadata) / sizeof(input_function_metadata[0]) == input_function_count, "input_function_metadata size mismatch with input_common. Did you forget to update "