Simplify ASSERT_SORT_ORDER

In practice this only looked at the name property, so we can simplify it
by using an ordinary template function instead of a macro.
This commit is contained in:
ridiculousfish 2021-07-15 13:15:24 -07:00
parent a638c4f01d
commit f345464879
6 changed files with 28 additions and 19 deletions

View file

@ -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<int> builtin_string(parser_t &parser, io_streams_t &streams, const wchar_t **argv) {

View file

@ -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;

View file

@ -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 <class T, size_t N> \
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<T, N>(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 <typename T, size_t N>
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

View file

@ -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);

View file

@ -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.

View file

@ -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 "