diff --git a/src/builtin_string.cpp b/src/builtin_string.cpp index c62b1754b..018f4b316 100644 --- a/src/builtin_string.cpp +++ b/src/builtin_string.cpp @@ -1783,7 +1783,7 @@ static constexpr const struct string_subcommand { {L"sub", &string_sub}, {L"trim", &string_trim}, {L"unescape", &string_unescape}, {L"upper", &string_upper}, }; -ASSERT_SORT_ORDER(string_subcommands, .name); +ASSERT_SORTED_BY_NAME(string_subcommands); /// The string builtin, for manipulating strings. maybe_t builtin_string(parser_t &parser, io_streams_t &streams, const wchar_t **argv) { diff --git a/src/color.cpp b/src/color.cpp index 2af5718e9..9b59aac5b 100644 --- a/src/color.cpp +++ b/src/color.cpp @@ -200,7 +200,7 @@ static constexpr named_color_t named_colors[] = { {L"purple", 5, {0x80, 0x00, 0x80}, true}, {L"red", 1, {0x80, 0x00, 0x00}, false}, {L"white", 7, {0xC0, 0xC0, 0xC0}, false}, {L"yellow", 3, {0x80, 0x80, 0x00}, false}, }; -ASSERT_SORT_ORDER(named_colors, .name); +ASSERT_SORTED_BY_NAME(named_colors); wcstring_list_t rgb_color_t::named_color_names() { wcstring_list_t result; diff --git a/src/common.h b/src/common.h index 8bb92a3b0..0cf7ce86e 100644 --- a/src/common.h +++ b/src/common.h @@ -710,20 +710,13 @@ constexpr size_t const_strlen(const T (&val)[N], size_t last_checked_idx = N, val[last_checked_idx - 1] ? first_nul_idx : last_checked_idx - 1); } -/// 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!"); +/// \return true if the array \p vals is sorted by its name property. +template +constexpr bool is_sorted_by_name(const T (&vals)[N], size_t idx = 1) { + return idx >= N ? true + : (const_strcmp(vals[idx - 1].name, vals[idx].name) <= 0 && + is_sorted_by_name(vals, idx + 1)); +} +#define ASSERT_SORTED_BY_NAME(x) static_assert(is_sorted_by_name(x), #x " not sorted by name") #endif // FISH_COMMON_H diff --git a/src/env.cpp b/src/env.cpp index ddc3aec4f..735412b45 100644 --- a/src/env.cpp +++ b/src/env.cpp @@ -107,7 +107,7 @@ static constexpr const electric_var_t electric_variables[] = { {L"umask", electric_var_t::fcomputed}, {L"version", electric_var_t::freadonly}, }; -ASSERT_SORT_ORDER(electric_variables, .name); +ASSERT_SORTED_BY_NAME(electric_variables); const electric_var_t *electric_var_t::for_name(const wchar_t *name) { auto begin = std::begin(electric_variables); diff --git a/src/fish_tests.cpp b/src/fish_tests.cpp index 94ea9d56b..2306e5f47 100644 --- a/src/fish_tests.cpp +++ b/src/fish_tests.cpp @@ -1698,12 +1698,28 @@ static void test_const_strcmp() { static_assert(const_strcmp("b", "aa") > 0, "const_strcmp failure"); } +static void test_is_sorted_by_name() { + struct named_t { + const wchar_t *name; + }; + + static constexpr named_t sorted[] = { + {L"a"}, {L"aa"}, {L"aaa"}, {L"aaa"}, {L"aaa"}, {L"aazz"}, {L"aazzzz"}, + }; + static_assert(is_sorted_by_name(sorted), "is_sorted_by_name failure"); + static constexpr named_t not_sorted[] = { + {L"a"}, {L"aa"}, {L"aaa"}, {L"q"}, {L"aazz"}, {L"aazz"}, {L"aazz"}, {L"aazzzz"}, + }; + static_assert(!is_sorted_by_name(not_sorted), "is_sorted_by_name failure"); +} + static void test_utility_functions() { say(L"Testing utility functions"); test_wcsfilecmp(); test_parse_util_cmdsubst_extent(); test_const_strlen(); test_const_strcmp(); + test_is_sorted_by_name(); } // UTF8 tests taken from Alexey Vatchenko's utf8 library. See http://www.bsdua.org/libbsdua.html. diff --git a/src/input.cpp b/src/input.cpp index 93a008d84..0e7f1d64b 100644 --- a/src/input.cpp +++ b/src/input.cpp @@ -165,7 +165,7 @@ static constexpr const input_function_metadata_t input_function_metadata[] = { {L"yank-pop", readline_cmd_t::yank_pop}, }; -ASSERT_SORT_ORDER(input_function_metadata, .name); +ASSERT_SORTED_BY_NAME(input_function_metadata); 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 "