char: use a static array for backends

Number and kinds of backends is known at compile-time, use a fixed-sized
static array to simplify iterations & lookups.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
Marc-André Lureau 2016-10-21 16:30:29 +03:00 committed by Paolo Bonzini
parent 0b812f3192
commit a1698bf183

View file

@ -4101,21 +4101,20 @@ static void qemu_chr_parse_udp(QemuOpts *opts, ChardevBackend *backend,
} }
} }
static GSList *backends; static const CharDriver *backends[CHARDEV_BACKEND_KIND__MAX];
void register_char_driver(const CharDriver *driver) void register_char_driver(const CharDriver *driver)
{ {
/* casting away const */ backends[driver->kind] = driver;
backends = g_slist_append(backends, (void *)driver);
} }
CharDriverState *qemu_chr_new_from_opts(QemuOpts *opts, CharDriverState *qemu_chr_new_from_opts(QemuOpts *opts,
Error **errp) Error **errp)
{ {
Error *local_err = NULL; Error *local_err = NULL;
CharDriver *cd; const CharDriver *cd = NULL;
CharDriverState *chr; CharDriverState *chr;
GSList *i; int i;
ChardevReturn *ret = NULL; ChardevReturn *ret = NULL;
ChardevBackend *backend; ChardevBackend *backend;
const char *name = qemu_opt_get(opts, "backend"); const char *name = qemu_opt_get(opts, "backend");
@ -4130,11 +4129,13 @@ CharDriverState *qemu_chr_new_from_opts(QemuOpts *opts,
if (is_help_option(name)) { if (is_help_option(name)) {
fprintf(stderr, "Available chardev backend types:\n"); fprintf(stderr, "Available chardev backend types:\n");
for (i = backends; i; i = i->next) { for (i = 0; i < ARRAY_SIZE(backends); i++) {
cd = i->data; cd = backends[i];
fprintf(stderr, "%s\n", ChardevBackendKind_lookup[cd->kind]); if (cd) {
if (cd->alias) { fprintf(stderr, "%s\n", ChardevBackendKind_lookup[cd->kind]);
fprintf(stderr, "%s\n", cd->alias); if (cd->alias) {
fprintf(stderr, "%s\n", cd->alias);
}
} }
} }
exit(0); exit(0);
@ -4145,15 +4146,17 @@ CharDriverState *qemu_chr_new_from_opts(QemuOpts *opts,
goto err; goto err;
} }
for (i = backends; i; i = i->next) { for (i = 0; i < ARRAY_SIZE(backends); i++) {
cd = i->data; cd = backends[i];
if (!cd) {
continue;
}
if (g_strcmp0(ChardevBackendKind_lookup[cd->kind], name) == 0 || if (g_strcmp0(ChardevBackendKind_lookup[cd->kind], name) == 0 ||
g_strcmp0(cd->alias, name) == 0) { g_strcmp0(cd->alias, name) == 0) {
break; break;
} }
} }
if (i == NULL) { if (i == ARRAY_SIZE(backends)) {
error_setg(errp, "chardev: backend \"%s\" not found", name); error_setg(errp, "chardev: backend \"%s\" not found", name);
goto err; goto err;
} }
@ -4370,11 +4373,15 @@ qmp_prepend_backend(ChardevBackendInfoList *list, const char *name)
ChardevBackendInfoList *qmp_query_chardev_backends(Error **errp) ChardevBackendInfoList *qmp_query_chardev_backends(Error **errp)
{ {
ChardevBackendInfoList *backend_list = NULL; ChardevBackendInfoList *backend_list = NULL;
CharDriver *c; const CharDriver *c;
GSList *i; int i;
for (i = 0; i < ARRAY_SIZE(backends); i++) {
c = backends[i];
if (!c) {
continue;
}
for (i = backends; i; i = i->next) {
c = i->data;
backend_list = qmp_prepend_backend(backend_list, backend_list = qmp_prepend_backend(backend_list,
ChardevBackendKind_lookup[c->kind]); ChardevBackendKind_lookup[c->kind]);
if (c->alias) { if (c->alias) {
@ -4835,9 +4842,8 @@ ChardevReturn *qmp_chardev_add(const char *id, ChardevBackend *backend,
{ {
ChardevReturn *ret = g_new0(ChardevReturn, 1); ChardevReturn *ret = g_new0(ChardevReturn, 1);
CharDriverState *chr = NULL; CharDriverState *chr = NULL;
const CharDriver *cd;
Error *local_err = NULL; Error *local_err = NULL;
GSList *i;
CharDriver *cd;
bool be_opened = true; bool be_opened = true;
chr = qemu_chr_find(id); chr = qemu_chr_find(id);
@ -4846,22 +4852,16 @@ ChardevReturn *qmp_chardev_add(const char *id, ChardevBackend *backend,
goto out_error; goto out_error;
} }
for (i = backends; i; i = i->next) { cd = (int)backend->type >= 0 && backend->type < ARRAY_SIZE(backends) ?
cd = i->data; backends[backend->type] : NULL;
if (cd == NULL) {
if (cd->kind == backend->type) { error_setg(errp, "chardev backend not available");
chr = cd->create(id, backend, ret, &be_opened, &local_err); goto out_error;
if (local_err) {
error_propagate(errp, local_err);
goto out_error;
}
break;
}
} }
if (chr == NULL) { chr = cd->create(id, backend, ret, &be_opened, &local_err);
assert(!i); if (local_err) {
error_setg(errp, "chardev backend not available"); error_propagate(errp, local_err);
goto out_error; goto out_error;
} }