summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSébastien Helleu <flashcode@flashtux.org>2023-02-23 07:35:21 +0100
committerSébastien Helleu <flashcode@flashtux.org>2023-03-16 20:42:19 +0100
commitd1adec29f9af2ddbc3513a88314b298254417bb5 (patch)
treed2065bdcea24969a0d40038fe213cbc7cb9b5008
parent5b5c9afa290bd444514c446ab6184c2ca55d9d72 (diff)
downloadweechat-d1adec29f9af2ddbc3513a88314b298254417bb5.zip
core: optimize search of key by reducing the number of splits into chunks
-rw-r--r--src/gui/gui-key.c115
1 files changed, 67 insertions, 48 deletions
diff --git a/src/gui/gui-key.c b/src/gui/gui-key.c
index eab368a26..6b121912b 100644
--- a/src/gui/gui-key.c
+++ b/src/gui/gui-key.c
@@ -1307,32 +1307,31 @@ gui_key_compare_chunks (const char **chunks, int chunks_count,
}
/*
- * Searches for a key (maybe part of string) for context default, search or
- * cursor (not for mouse).
+ * Searches key chunks for context default, search or cursor (not for mouse).
+ * It can be part of key chunks or exact match.
*
- * If exact match is found, *exact_match is set to 1, otherwise to 0.
+ * Parameter "chunks1" is the raw key split into chunks, and "chunks2" is the
+ * key with alias split into chunks (at least one of the chunks must be non
+ * NULL).
*
* Returns pointer to key found, NULL if not found.
+ * In case of exact match, *exact_match is set to 1, otherwise 0.
*/
struct t_gui_key *
gui_key_search_part (struct t_gui_buffer *buffer, int context,
- const char *key, const char *key_alias,
+ const char **chunks1, int chunks1_count,
+ const char **chunks2, int chunks2_count,
int *exact_match)
{
struct t_gui_key *ptr_key;
- char **chunks, **chunks_alias;
- int rc, chunks_count, chunks_alias_count;
+ int rc;
- if (!key || !exact_match)
+ if ((!chunks1 && !chunks2) || !exact_match)
return NULL;
*exact_match = 0;
- chunks = string_split (key, ",", NULL, 0, 0, &chunks_count);
- chunks_alias = (key_alias) ?
- string_split (key_alias, ",", NULL, 0, 0, &chunks_alias_count) : NULL;
-
for (ptr_key = (buffer) ? buffer->keys : gui_keys[context]; ptr_key;
ptr_key = ptr_key->next_key)
{
@@ -1340,20 +1339,23 @@ gui_key_search_part (struct t_gui_buffer *buffer, int context,
&& ((context != GUI_KEY_CONTEXT_CURSOR)
|| (ptr_key->key[0] != '@')))
{
- rc = gui_key_compare_chunks ((const char **)chunks,
- chunks_count,
- (const char **)ptr_key->chunks,
- ptr_key->chunks_count);
- if (rc > 0)
+ if (chunks1)
{
- if (rc == 2)
- *exact_match = 1;
- break;
+ rc = gui_key_compare_chunks (chunks1,
+ chunks1_count,
+ (const char **)ptr_key->chunks,
+ ptr_key->chunks_count);
+ if (rc > 0)
+ {
+ if (rc == 2)
+ *exact_match = 1;
+ break;
+ }
}
- if (chunks_alias)
+ if (chunks2)
{
- rc = gui_key_compare_chunks ((const char **)chunks_alias,
- chunks_alias_count,
+ rc = gui_key_compare_chunks (chunks2,
+ chunks2_count,
(const char **)ptr_key->chunks,
ptr_key->chunks_count);
if (rc > 0)
@@ -1366,11 +1368,6 @@ gui_key_search_part (struct t_gui_buffer *buffer, int context,
}
}
- if (chunks)
- string_free_split (chunks);
- if (chunks_alias)
- string_free_split (chunks_alias);
-
return ptr_key;
}
@@ -1869,11 +1866,10 @@ int
gui_key_pressed (const char *key_str)
{
int i, insert_into_input, context, length, length_key, signal_sent;
- int rc, rc_expand, exact_match;
+ int rc, rc_expand, exact_match, chunks1_count, chunks2_count;
struct t_gui_key *ptr_key;
char *pos, signal_name[128], **commands;
- char *key_name, *key_name_alias;
- const char *ptr_key_name2;
+ char *key_name, *key_name_alias, **chunks1, **chunks2;
signal_sent = 0;
@@ -1944,42 +1940,65 @@ gui_key_pressed (const char *key_str)
ptr_key = NULL;
exact_match = 0;
- ptr_key_name2 = (string_strcmp (key_name, key_name_alias) != 0) ?
- key_name_alias : NULL;
+
+ chunks1 = string_split (key_name, ",", NULL, 0, 0, &chunks1_count);
+ chunks2 = (string_strcmp (key_name, key_name_alias) != 0) ?
+ string_split (key_name_alias, ",", NULL, 0, 0, &chunks2_count) : NULL;
context = gui_key_get_current_context ();
switch (context)
{
case GUI_KEY_CONTEXT_DEFAULT:
/* look for key combo in key table for current buffer */
- ptr_key = gui_key_search_part (gui_current_window->buffer,
- GUI_KEY_CONTEXT_DEFAULT,
- key_name, ptr_key_name2,
- &exact_match);
+ ptr_key = gui_key_search_part (
+ gui_current_window->buffer,
+ GUI_KEY_CONTEXT_DEFAULT,
+ (const char **)chunks1, chunks1_count,
+ (const char **)chunks2, chunks2_count,
+ &exact_match);
/* if key is not found for buffer, then look in general table */
if (!ptr_key)
- ptr_key = gui_key_search_part (NULL, GUI_KEY_CONTEXT_DEFAULT,
- key_name, ptr_key_name2,
- &exact_match);
+ {
+ ptr_key = gui_key_search_part (
+ NULL,
+ GUI_KEY_CONTEXT_DEFAULT,
+ (const char **)chunks1, chunks1_count,
+ (const char **)chunks2, chunks2_count,
+ &exact_match);
+ }
break;
case GUI_KEY_CONTEXT_SEARCH:
- ptr_key = gui_key_search_part (NULL, GUI_KEY_CONTEXT_SEARCH,
- key_name, ptr_key_name2,
- &exact_match);
+ ptr_key = gui_key_search_part (
+ NULL,
+ GUI_KEY_CONTEXT_SEARCH,
+ (const char **)chunks1, chunks1_count,
+ (const char **)chunks2, chunks2_count,
+ &exact_match);
if (!ptr_key)
{
- ptr_key = gui_key_search_part (NULL, GUI_KEY_CONTEXT_DEFAULT,
- key_name, ptr_key_name2,
- &exact_match);
+ ptr_key = gui_key_search_part (
+ NULL,
+ GUI_KEY_CONTEXT_DEFAULT,
+ (const char **)chunks1, chunks1_count,
+ (const char **)chunks2, chunks2_count,
+ &exact_match);
}
break;
case GUI_KEY_CONTEXT_CURSOR:
- ptr_key = gui_key_search_part (NULL, GUI_KEY_CONTEXT_CURSOR,
- key_name, ptr_key_name2,
- &exact_match);
+ ptr_key = gui_key_search_part (
+ NULL,
+ GUI_KEY_CONTEXT_CURSOR,
+ (const char **)chunks1, chunks1_count,
+ (const char **)chunks2, chunks2_count,
+ &exact_match);
break;
}
+ if (chunks1)
+ string_free_split (chunks1);
+ if (chunks2)
+ string_free_split (chunks2);
+
if (ptr_key)
{
/*