diff options
author | Corey Farrell <git@cfware.com> | 2017-11-09 00:42:10 -0500 |
---|---|---|
committer | Corey Farrell <git@cfware.com> | 2017-11-21 09:39:19 -0500 |
commit | 9587a61f4c40d5d7911b1069f4fa353012018e2b (patch) | |
tree | 827c31eebbc86a642abe7411013097f047301de5 /main/cli.c | |
parent | a02cbc2ef3903c68737fddee79d8db1d66623ab4 (diff) |
CLI: Create ast_cli_completion_add function.
Some completion generators are very inefficent due to the way CLI
requests matches one at a time. ast_cli_completion_add can be called
multiple times during one invokation of a CLI generator to add all
results without having to reinitialize the search state for each match.
Change-Id: I73d26d270bbbe1e3e6390799cfc1b639e39cceec
Diffstat (limited to 'main/cli.c')
-rw-r--r-- | main/cli.c | 55 |
1 files changed, 53 insertions, 2 deletions
diff --git a/main/cli.c b/main/cli.c index 1653838ea..0f023b29f 100644 --- a/main/cli.c +++ b/main/cli.c @@ -2512,6 +2512,44 @@ char **ast_cli_completion_matches(const char *text, const char *word) return match_list; } +AST_THREADSTORAGE_RAW(completion_storage); + +/*! + * \internal + * \brief Add a value to the vector. + * + * \param vec Vector to add \a value to. Must be from threadstorage. + * \param value The value to add. + * + * \retval 0 Success + * \retval -1 Failure + */ +static int cli_completion_vector_add(struct ast_vector_string *vec, char *value) +{ + if (!value) { + return 0; + } + + if (!vec || AST_VECTOR_ADD_SORTED(vec, value, strcasecmp)) { + if (vec) { + ast_threadstorage_set_ptr(&completion_storage, NULL); + + AST_VECTOR_CALLBACK_VOID(vec, ast_free); + AST_VECTOR_FREE(vec); + } + ast_free(value); + + return -1; + } + + return 0; +} + +int ast_cli_completion_add(char *value) +{ + return cli_completion_vector_add(ast_threadstorage_get_ptr(&completion_storage), value); +} + struct ast_vector_string *ast_cli_completion_vector(const char *text, const char *word) { char *retstr, *prevstr; @@ -2519,13 +2557,23 @@ struct ast_vector_string *ast_cli_completion_vector(const char *text, const char size_t which = 0; struct ast_vector_string *vec = ast_calloc(1, sizeof(*vec)); + /* Recursion into this function is a coding error. */ + ast_assert(!ast_threadstorage_get_ptr(&completion_storage)); + if (!vec) { return NULL; } + if (ast_threadstorage_set_ptr(&completion_storage, vec)) { + ast_log(LOG_ERROR, "Failed to initialize threadstorage for completion.\n"); + ast_free(vec); + + return NULL; + } + while ((retstr = ast_cli_generator(text, word, which)) != NULL) { - if (AST_VECTOR_ADD_SORTED(vec, retstr, strcasecmp)) { - ast_free(retstr); + if (cli_completion_vector_add(vec, retstr)) { + ast_threadstorage_set_ptr(&completion_storage, NULL); goto vector_cleanup; } @@ -2533,6 +2581,8 @@ struct ast_vector_string *ast_cli_completion_vector(const char *text, const char ++which; } + ast_threadstorage_set_ptr(&completion_storage, NULL); + if (!AST_VECTOR_SIZE(vec)) { AST_VECTOR_PTR_FREE(vec); @@ -2571,6 +2621,7 @@ struct ast_vector_string *ast_cli_completion_vector(const char *text, const char retstr = ast_strndup(AST_VECTOR_GET(vec, 0), max_equal); if (!retstr || AST_VECTOR_INSERT_AT(vec, 0, retstr)) { ast_free(retstr); + goto vector_cleanup; } |