input: use bstr for section name

Resolves mixed use of bstr in internal processing and char* for storage.
Also makes faster comparision when searching for section and resolves
comparision when name contains null chars.
This commit is contained in:
Kacper Michajłow 2024-08-03 10:27:22 +02:00
parent aa35f2e4bd
commit 1a27f3caf7
2 changed files with 56 additions and 55 deletions

View File

@ -105,7 +105,7 @@ typedef struct mp_cmd {
int flags; // mp_cmd_flags bitfield
char *original;
char *desc; // (usually NULL since stripped away later)
char *input_section;
bstr input_section;
bool is_up_down : 1;
bool is_up : 1;
bool emit_on_up : 1;

View File

@ -70,7 +70,7 @@ struct cmd_bind_section {
char *owner;
struct cmd_bind *binds;
int num_binds;
char *section;
bstr section;
struct mp_rect mouse_area; // set at runtime, if at all
bool mouse_area_set; // mouse_area is valid and should be tested
};
@ -78,7 +78,7 @@ struct cmd_bind_section {
#define MP_MAX_SOURCES 10
struct active_section {
char *name;
bstr name;
int flags;
};
@ -129,7 +129,7 @@ struct input_ctx {
// Mouse position on the consumer side (as command.c sees it)
int mouse_x, mouse_y;
int mouse_hover; // updated on mouse-enter/leave
char *mouse_section; // last section to receive mouse event
bstr mouse_section; // last section to receive mouse event
// Mouse position on the producer side (as the VO sees it)
// Unlike mouse_x/y, this can be used to resolve mouse click bindings.
@ -168,7 +168,7 @@ struct input_ctx {
};
static int parse_config(struct input_ctx *ictx, bool builtin, bstr data,
const char *location, const char *restrict_section);
const char *location, bstr section);
static void close_input_sources(struct input_ctx *ictx);
static bool test_mouse(struct input_ctx *ictx, int x, int y, int rej_flags);
@ -316,9 +316,9 @@ static void append_bind_info(struct input_ctx *ictx, char **pmsg,
msg = talloc_asprintf_append(msg, " '%s'", stripped);
if (!cmd)
msg = talloc_asprintf_append(msg, " (invalid)");
if (strcmp(bind->owner->section, "default") != 0)
msg = talloc_asprintf_append(msg, " in section {%s}",
bind->owner->section);
if (bstr_equals0(bind->owner->section, "default"))
msg = talloc_asprintf_append(msg, " in section {%.*s}",
BSTR_P(bind->owner->section));
msg = talloc_asprintf_append(msg, " in %s", bind->location);
if (bind->is_builtin)
msg = talloc_asprintf_append(msg, " (default)");
@ -371,7 +371,7 @@ static struct cmd_bind_section *find_section(struct input_ctx *ictx,
{
for (int n = 0; n < ictx->num_sections; n++) {
struct cmd_bind_section *bs = ictx->sections[n];
if (bstr_equals0(section, bs->section))
if (bstr_equals(section, bs->section))
return bs;
}
return NULL;
@ -387,7 +387,7 @@ static struct cmd_bind_section *get_bind_section(struct input_ctx *ictx,
return bind_section;
bind_section = talloc_ptrtype(ictx, bind_section);
*bind_section = (struct cmd_bind_section) {
.section = bstrdup0(bind_section, section),
.section = bstrdup(bind_section, section),
.mouse_area = {INT_MIN, INT_MIN, INT_MAX, INT_MAX},
.mouse_area_set = true,
};
@ -403,9 +403,9 @@ static void key_buf_add(int *buf, int code)
}
static struct cmd_bind *find_bind_for_key_section(struct input_ctx *ictx,
char *section, int code)
bstr section, int code)
{
struct cmd_bind_section *bs = get_bind_section(ictx, bstr0(section));
struct cmd_bind_section *bs = get_bind_section(ictx, section);
if (!bs->num_binds)
return NULL;
@ -439,9 +439,9 @@ static struct cmd_bind *find_bind_for_key_section(struct input_ctx *ictx,
}
static struct cmd_bind *find_any_bind_for_key(struct input_ctx *ictx,
char *force_section, int code)
bstr force_section, int code)
{
if (force_section)
if (force_section.len)
return find_bind_for_key_section(ictx, force_section, code);
bool use_mouse = MP_KEY_DEPENDS_ON_MOUSE_POS(code);
@ -484,7 +484,7 @@ static struct cmd_bind *find_any_bind_for_key(struct input_ctx *ictx,
return best_bind;
}
static mp_cmd_t *get_cmd_from_keys(struct input_ctx *ictx, char *force_section,
static mp_cmd_t *get_cmd_from_keys(struct input_ctx *ictx, bstr force_section,
int code)
{
if (ictx->opts->test)
@ -513,8 +513,8 @@ static mp_cmd_t *get_cmd_from_keys(struct input_ctx *ictx, char *force_section,
if (ret) {
ret->input_section = cmd->owner->section;
ret->key_name = talloc_steal(ret, mp_input_get_key_combo_name(&code, 1));
MP_TRACE(ictx, "key '%s' -> '%s' in '%s'\n",
ret->key_name, cmd->cmd, ret->input_section);
MP_TRACE(ictx, "key '%s' -> '%s' in '%.*s'\n",
ret->key_name, cmd->cmd, BSTR_P(ret->input_section));
if (MP_KEY_IS_UNICODE(code)) {
bstr text = {0};
mp_append_utf8_bstr(ret, &text, code);
@ -533,16 +533,16 @@ static mp_cmd_t *get_cmd_from_keys(struct input_ctx *ictx, char *force_section,
static void update_mouse_section(struct input_ctx *ictx)
{
struct cmd_bind *bind =
find_any_bind_for_key(ictx, NULL, MP_KEY_MOUSE_MOVE);
find_any_bind_for_key(ictx, (bstr){0}, MP_KEY_MOUSE_MOVE);
char *new_section = bind ? bind->owner->section : "default";
bstr new_section = bind ? bind->owner->section : bstr0("default");
char *old = ictx->mouse_section;
bstr old = ictx->mouse_section;
ictx->mouse_section = new_section;
if (strcmp(old, ictx->mouse_section) != 0) {
MP_TRACE(ictx, "input: switch section %s -> %s\n",
old, ictx->mouse_section);
if (!bstr_equals(old, ictx->mouse_section)) {
MP_TRACE(ictx, "input: switch section %.*s -> %.*s\n",
BSTR_P(old), BSTR_P(ictx->mouse_section));
queue_cmd(ictx, get_cmd_from_keys(ictx, old, MP_KEY_MOUSE_LEAVE));
}
}
@ -586,7 +586,7 @@ static bool should_drop_cmd(struct input_ctx *ictx, struct mp_cmd *cmd)
static struct mp_cmd *resolve_key(struct input_ctx *ictx, int code)
{
update_mouse_section(ictx);
struct mp_cmd *cmd = get_cmd_from_keys(ictx, NULL, code);
struct mp_cmd *cmd = get_cmd_from_keys(ictx, (bstr){0}, code);
key_buf_add(ictx->key_history, code);
if (cmd && !cmd->def->is_ignore && !should_drop_cmd(ictx, cmd))
return cmd;
@ -765,7 +765,7 @@ static void feed_key(struct input_ctx *ictx, int code, double scale,
ictx->mouse_hover = unmod == MP_KEY_MOUSE_ENTER;
update_mouse_section(ictx);
mp_cmd_t *cmd = get_cmd_from_keys(ictx, NULL, code);
mp_cmd_t *cmd = get_cmd_from_keys(ictx, (bstr){0}, code);
if (!cmd) // queue dummy cmd so that mouse-pos can notify observers
cmd = mp_input_parse_cmd(ictx, bstr0("ignore"), "<internal>");
queue_cmd(ictx, cmd);
@ -907,7 +907,7 @@ static void set_mouse_pos(struct input_ctx *ictx, int x, int y)
ictx->mouse_vo_y = y;
update_mouse_section(ictx);
struct mp_cmd *cmd = get_cmd_from_keys(ictx, NULL, MP_KEY_MOUSE_MOVE);
struct mp_cmd *cmd = get_cmd_from_keys(ictx, (bstr){0}, MP_KEY_MOUSE_MOVE);
if (!cmd)
cmd = mp_input_parse_cmd(ictx, bstr0("ignore"), "<internal>");
@ -1060,7 +1060,7 @@ static bool test_mouse(struct input_ctx *ictx, int x, int y, int rej_flags)
struct active_section *as = &ictx->active_sections[i];
if (as->flags & rej_flags)
continue;
struct cmd_bind_section *s = get_bind_section(ictx, bstr0(as->name));
struct cmd_bind_section *s = get_bind_section(ictx, as->name);
if (s->mouse_area_set && test_rect(&s->mouse_area, x, y)) {
res = true;
break;
@ -1197,19 +1197,19 @@ void mp_input_get_mouse_pos(struct input_ctx *ictx, int *x, int *y, int *hover)
// If name is NULL, return "default".
// Return a statically allocated name of the section (i.e. return value never
// gets deallocated).
static char *normalize_section(struct input_ctx *ictx, char *name)
static bstr normalize_section(struct input_ctx *ictx, bstr name)
{
return get_bind_section(ictx, bstr0(name))->section;
return get_bind_section(ictx, name)->section;
}
static void disable_section(struct input_ctx *ictx, char *name)
static void disable_section(struct input_ctx *ictx, bstr name)
{
name = normalize_section(ictx, name);
// Remove old section, or make sure it's on top if re-enabled
for (int i = ictx->num_active_sections - 1; i >= 0; i--) {
struct active_section *as = &ictx->active_sections[i];
if (strcmp(as->name, name) == 0) {
if (bstr_equals(as->name, name)) {
MP_TARRAY_REMOVE_AT(ictx->active_sections,
ictx->num_active_sections, i);
}
@ -1219,18 +1219,19 @@ static void disable_section(struct input_ctx *ictx, char *name)
void mp_input_disable_section(struct input_ctx *ictx, char *name)
{
input_lock(ictx);
disable_section(ictx, name);
disable_section(ictx, bstr0(name));
input_unlock(ictx);
}
void mp_input_enable_section(struct input_ctx *ictx, char *name, int flags)
{
bstr bname = bstr0(name);
input_lock(ictx);
name = normalize_section(ictx, name);
bname = normalize_section(ictx, bname);
disable_section(ictx, name);
disable_section(ictx, bname);
MP_TRACE(ictx, "enable section '%s'\n", name);
MP_TRACE(ictx, "enable section '%.*s'\n", BSTR_P(bname));
int top = ictx->num_active_sections;
if (!(flags & MP_INPUT_ON_TOP)) {
@ -1241,11 +1242,11 @@ void mp_input_enable_section(struct input_ctx *ictx, char *name, int flags)
}
}
MP_TARRAY_INSERT_AT(ictx, ictx->active_sections, ictx->num_active_sections,
top, (struct active_section){name, flags});
top, (struct active_section){bname, flags});
MP_TRACE(ictx, "active section stack:\n");
for (int n = 0; n < ictx->num_active_sections; n++) {
MP_TRACE(ictx, " %s %d\n", ictx->active_sections[n].name,
MP_TRACE(ictx, " %.*s %d\n", BSTR_P(ictx->active_sections[n].name),
ictx->active_sections[n].flags);
}
@ -1292,13 +1293,14 @@ static void remove_binds(struct cmd_bind_section *bs, bool builtin)
void mp_input_define_section(struct input_ctx *ictx, char *name, char *location,
char *contents, bool builtin, char *owner)
{
if (!name || !name[0])
bstr bname = bstr0(name);
if (!bname.len)
return; // parse_config() changes semantics with restrict_section==empty
input_lock(ictx);
// Delete:
struct cmd_bind_section *bs = get_bind_section(ictx, bstr0(name));
struct cmd_bind_section *bs = get_bind_section(ictx, bname);
if ((!bs->owner || (owner && strcmp(bs->owner, owner) != 0)) &&
strcmp(bs->section, "default") != 0)
!bstr_equals0(bs->section, "default"))
{
talloc_free(bs->owner);
bs->owner = talloc_strdup(bs, owner);
@ -1306,10 +1308,10 @@ void mp_input_define_section(struct input_ctx *ictx, char *name, char *location,
remove_binds(bs, builtin);
if (contents && contents[0]) {
// Redefine:
parse_config(ictx, builtin, bstr0(contents), location, name);
parse_config(ictx, builtin, bstr0(contents), location, bname);
} else {
// Disable:
disable_section(ictx, name);
disable_section(ictx, bname);
}
input_unlock(ictx);
}
@ -1375,17 +1377,17 @@ static void bind_keys(struct input_ctx *ictx, bool builtin, bstr section,
memcpy(bind->keys, keys, num_keys * sizeof(bind->keys[0]));
if (mp_msg_test(ictx->log, MSGL_DEBUG)) {
char *s = mp_input_get_key_combo_name(keys, num_keys);
MP_TRACE(ictx, "add: section='%s' key='%s'%s cmd='%s' location='%s'\n",
bind->owner->section, s, bind->is_builtin ? " builtin" : "",
MP_TRACE(ictx, "add: section='%.*s' key='%s'%s cmd='%s' location='%s'\n",
BSTR_P(bind->owner->section), s, bind->is_builtin ? " builtin" : "",
bind->cmd, bind->location);
talloc_free(s);
}
}
// restrict_section: every entry is forced to this section name
// if NULL, load normally and allow any sections
// section: every entry is forced to this section name
// if NULL, load normally and allow any sections
static int parse_config(struct input_ctx *ictx, bool builtin, bstr data,
const char *location, const char *restrict_section)
const char *location, bstr section)
{
int n_binds = 0;
int line_no = 0;
@ -1432,7 +1434,6 @@ static int parse_config(struct input_ctx *ictx, bool builtin, bstr data,
}
talloc_free(name);
bstr section = bstr0(restrict_section);
if (!section.len) {
if (bstr_startswith0(command, "{")) {
int p = bstrchr(command, '}');
@ -1479,7 +1480,7 @@ static bool parse_config_file(struct input_ctx *ictx, char *file)
bstr data = stream_read_complete(s, tmp, 1000000);
if (data.start) {
MP_VERBOSE(ictx, "Parsing input config file %s\n", file);
int num = parse_config(ictx, false, data, file, NULL);
int num = parse_config(ictx, false, data, file, (bstr){0});
MP_VERBOSE(ictx, "Input config file %s parsed: %d binds\n", file, num);
r = true;
} else {
@ -1502,7 +1503,7 @@ struct input_ctx *mp_input_init(struct mpv_global *global,
.global = global,
.ar_state = -1,
.log = mp_log_new(ictx, global->log, "input"),
.mouse_section = "default",
.mouse_section = bstr0("default"),
.opts_cache = m_config_cache_alloc(ictx, global, &input_config),
.wakeup_cb = wakeup_cb,
.wakeup_ctx = wakeup_ctx,
@ -1559,7 +1560,7 @@ void mp_input_load_config(struct input_ctx *ictx)
bstr line = bstr_getline(builtin, &builtin);
bstr_eatstart0(&line, "#");
if (!bstr_startswith0(line, " "))
parse_config(ictx, true, line, "<builtin>", NULL);
parse_config(ictx, true, line, "<builtin>", (bstr){0});
}
bool config_ok = false;
@ -1679,8 +1680,8 @@ void mp_input_bind_key(struct input_ctx *ictx, int key, bstr command)
memcpy(bind->keys, &key, 1 * sizeof(bind->keys[0]));
if (mp_msg_test(ictx->log, MSGL_DEBUG)) {
char *s = mp_input_get_key_combo_name(&key, 1);
MP_TRACE(ictx, "add:section='%s' key='%s'%s cmd='%s' location='%s'\n",
bind->owner->section, s, bind->is_builtin ? " builtin" : "",
MP_TRACE(ictx, "add:section='%.*s' key='%s'%s cmd='%s' location='%s'\n",
BSTR_P(bind->owner->section), s, bind->is_builtin ? " builtin" : "",
bind->cmd, bind->location);
talloc_free(s);
}
@ -1699,7 +1700,7 @@ struct mpv_node mp_input_get_bindings(struct input_ctx *ictx)
for (int i = 0; i < ictx->num_active_sections; i++) {
struct active_section *as = &ictx->active_sections[i];
if (strcmp(as->name, s->section) == 0) {
if (bstr_equals(as->name, s->section)) {
priority = i;
break;
}
@ -1718,7 +1719,7 @@ struct mpv_node mp_input_get_bindings(struct input_ctx *ictx)
if (b_priority >= 0 && !b->is_builtin)
b_priority += ictx->num_active_sections;
node_map_add_string(entry, "section", s->section);
node_map_add_string(entry, "section", s->section.start);
if (s->owner)
node_map_add_string(entry, "owner", s->owner);
node_map_add_string(entry, "cmd", b->cmd);