refactor(highlight): merge redundant attr_entries and attr_entry_ids structs

An insert-only set now defines a monotonically increasing ordering by
itself. It can be used to both lookup the key from index, and vice versa.
This commit is contained in:
bfredl 2023-09-12 11:54:36 +02:00
parent 1c4a93b591
commit a6d745865a
4 changed files with 33 additions and 37 deletions

View File

@ -40,13 +40,13 @@
static bool hlstate_active = false;
static kvec_t(HlEntry) attr_entries = KV_INITIAL_VALUE;
static Map(HlEntry, int) attr_entry_ids = MAP_INIT;
static Set(HlEntry) attr_entries = SET_INIT;
static Map(int, int) combine_attr_entries = MAP_INIT;
static Map(int, int) blend_attr_entries = MAP_INIT;
static Map(int, int) blendthrough_attr_entries = MAP_INIT;
#define attr_entry(i) attr_entries.keys[i]
/// highlight entries private to a namespace
static Map(ColorKey, ColorItem) ns_hls;
typedef int NSHlAttr[HLF_COUNT + 1];
@ -55,8 +55,8 @@ static PMap(int) ns_hl_attr;
void highlight_init(void)
{
// index 0 is no attribute, add dummy entry:
kv_push(attr_entries, ((HlEntry){ .attr = HLATTRS_INIT, .kind = kHlUnknown,
.id1 = 0, .id2 = 0 }));
set_put(HlEntry, &attr_entries, ((HlEntry){ .attr = HLATTRS_INIT, .kind = kHlInvalid,
.id1 = 0, .id2 = 0 }));
}
/// @return true if hl table was reset
@ -77,6 +77,7 @@ bool highlight_use_hlstate(void)
/// @return 0 for error.
static int get_attr_entry(HlEntry entry)
{
bool retried = false;
if (!hlstate_active) {
// This information will not be used, erase it and reduce the table size.
entry.kind = kHlUnknown;
@ -84,17 +85,19 @@ static int get_attr_entry(HlEntry entry)
entry.id2 = 0;
}
int id = map_get(HlEntry, int)(&attr_entry_ids, entry);
if (id > 0) {
return id;
retry: {}
MhPutStatus status;
uint32_t k = set_put_idx(HlEntry, &attr_entries, entry, &status);
if (status == kMHExisting) {
return (int)k;
}
static bool recursive = false;
if (kv_size(attr_entries) > MAX_TYPENR) {
if (set_size(&attr_entries) > MAX_TYPENR) {
// Running out of attribute entries! remove all attributes, and
// compute new ones for all groups.
// When called recursively, we are really out of numbers.
if (recursive) {
if (recursive || retried) {
emsg(_("E424: Too many different highlighting attributes in use"));
return 0;
}
@ -107,17 +110,12 @@ static int get_attr_entry(HlEntry entry)
// This entry is now invalid, don't put it
return 0;
}
retried = true;
goto retry;
}
size_t next_id = kv_size(attr_entries);
if (next_id > INT_MAX) {
ELOG("The index on attr_entries has overflowed");
return 0;
}
id = (int)next_id;
kv_push(attr_entries, entry);
map_put(HlEntry, int)(&attr_entry_ids, entry, id);
// new attr id, send event to remote ui:s
int id = (int)k;
Array inspect = hl_inspect(id);
@ -131,10 +129,10 @@ static int get_attr_entry(HlEntry entry)
/// When a UI connects, we need to send it the table of highlights used so far.
void ui_send_all_hls(UI *ui)
{
for (size_t i = 1; i < kv_size(attr_entries); i++) {
for (size_t i = 1; i < set_size(&attr_entries); i++) {
Array inspect = hl_inspect((int)i);
remote_ui_hl_attr_define(ui, (Integer)i, kv_A(attr_entries, i).attr,
kv_A(attr_entries, i).attr, inspect);
HlAttrs attr = attr_entry(i).attr;
remote_ui_hl_attr_define(ui, (Integer)i, attr, attr, inspect);
api_free_array(inspect);
}
for (size_t hlf = 0; hlf < HLF_COUNT; hlf++) {
@ -364,7 +362,7 @@ void update_window_hl(win_T *wp, bool invalid)
// if blend= attribute is not set, 'winblend' value overrides it.
if (wp->w_floating && wp->w_p_winbl > 0) {
HlEntry entry = kv_A(attr_entries, wp->w_hl_attr_normal);
HlEntry entry = attr_entry(wp->w_hl_attr_normal);
if (entry.attr.hl_blend == -1) {
entry.attr.hl_blend = (int)wp->w_p_winbl;
wp->w_hl_attr_normal = get_attr_entry(entry);
@ -401,7 +399,7 @@ void update_window_hl(win_T *wp, bool invalid)
// if blend= attribute is not set, 'winblend' value overrides it.
if (wp->w_floating && wp->w_p_winbl > 0) {
HlEntry entry = kv_A(attr_entries, wp->w_hl_attr_normalnc);
HlEntry entry = attr_entry(wp->w_hl_attr_normalnc);
if (entry.attr.hl_blend == -1) {
entry.attr.hl_blend = (int)wp->w_p_winbl;
wp->w_hl_attr_normalnc = get_attr_entry(entry);
@ -490,8 +488,8 @@ int hl_get_term_attr(HlAttrs *aep)
void clear_hl_tables(bool reinit)
{
if (reinit) {
kv_size(attr_entries) = 1;
map_clear(HlEntry, &attr_entry_ids);
set_clear(HlEntry, &attr_entries);
highlight_init();
map_clear(int, &combine_attr_entries);
map_clear(int, &blend_attr_entries);
map_clear(int, &blendthrough_attr_entries);
@ -500,8 +498,7 @@ void clear_hl_tables(bool reinit)
highlight_changed();
screen_invalidate_highlights();
} else {
kv_destroy(attr_entries);
map_destroy(HlEntry, &attr_entry_ids);
set_destroy(HlEntry, &attr_entries);
map_destroy(int, &combine_attr_entries);
map_destroy(int, &blend_attr_entries);
map_destroy(int, &blendthrough_attr_entries);
@ -809,11 +806,11 @@ static int hl_cterm2rgb_color(int nr)
/// Get highlight attributes for a attribute code
HlAttrs syn_attr2entry(int attr)
{
if (attr <= 0 || attr >= (int)kv_size(attr_entries)) {
if (attr <= 0 || attr >= (int)set_size(&attr_entries)) {
// invalid attribute code, or the tables were cleared
return HLATTRS_INIT;
}
return kv_A(attr_entries, attr).attr;
return attr_entry(attr).attr;
}
/// Gets highlight description for id `attr_id` as a map.
@ -825,7 +822,7 @@ Dictionary hl_get_attr_by_id(Integer attr_id, Boolean rgb, Arena *arena, Error *
return dic;
}
if (attr_id <= 0 || attr_id >= (int)kv_size(attr_entries)) {
if (attr_id <= 0 || attr_id >= (int)set_size(&attr_entries)) {
api_set_error(err, kErrorTypeException,
"Invalid attribute id: %" PRId64, attr_id);
return dic;
@ -1132,11 +1129,11 @@ Array hl_inspect(int attr)
static void hl_inspect_impl(Array *arr, int attr)
{
Dictionary item = ARRAY_DICT_INIT;
if (attr <= 0 || attr >= (int)kv_size(attr_entries)) {
if (attr <= 0 || attr >= (int)set_size(&attr_entries)) {
return;
}
HlEntry e = kv_A(attr_entries, attr);
HlEntry e = attr_entry(attr);
switch (e.kind) {
case kHlSyntax:
PUT(item, "kind", CSTR_TO_OBJ("syntax"));
@ -1165,6 +1162,7 @@ static void hl_inspect_impl(Array *arr, int attr)
return;
case kHlUnknown:
case kHlInvalid:
return;
}
PUT(item, "id", INTEGER_OBJ(attr));

View File

@ -219,6 +219,7 @@ typedef enum {
kHlCombine,
kHlBlend,
kHlBlendThrough,
kHlInvalid,
} HlKind;
typedef struct {

View File

@ -196,9 +196,6 @@ void mh_clear(MapHash *h)
#define KEY_NAME(x) x##HlEntry
#include "nvim/map_key_impl.c.h"
#define VAL_NAME(x) quasiquote(x, int)
#include "nvim/map_value_impl.c.h"
#undef VAL_NAME
#undef KEY_NAME
#define KEY_NAME(x) x##ColorKey

View File

@ -142,7 +142,6 @@ MAP_DECLS(uint64_t, uint64_t)
MAP_DECLS(int64_t, int64_t)
MAP_DECLS(int64_t, ptr_t)
MAP_DECLS(uint32_t, uint32_t)
MAP_DECLS(HlEntry, int)
MAP_DECLS(String, int)
MAP_DECLS(int, String)
MAP_DECLS(ColorKey, ColorItem)
@ -150,6 +149,7 @@ MAP_DECLS(ColorKey, ColorItem)
#define set_has(T, set, key) set_has_##T(set, key)
#define set_put(T, set, key) set_put_##T(set, key, NULL)
#define set_put_ref(T, set, key, key_alloc) set_put_##T(set, key, key_alloc)
#define set_put_idx(T, set, key, status) mh_put_##T(set, key, status)
#define set_del(T, set, key) set_del_##T(set, key)
#define set_destroy(T, set) (xfree((set)->keys), xfree((set)->h.hash))
#define set_clear(T, set) mh_clear(&(set)->h)