summaryrefslogtreecommitdiff
path: root/main/cli.c
diff options
context:
space:
mode:
authorCorey Farrell <git@cfware.com>2017-11-09 00:42:10 -0500
committerCorey Farrell <git@cfware.com>2017-11-21 09:39:19 -0500
commit9587a61f4c40d5d7911b1069f4fa353012018e2b (patch)
tree827c31eebbc86a642abe7411013097f047301de5 /main/cli.c
parenta02cbc2ef3903c68737fddee79d8db1d66623ab4 (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.c55
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;
}