From abe1465a1ab552cd188b57f58404024aeec78fb0 Mon Sep 17 00:00:00 2001 From: Naveen Albert Date: Sun, 11 Sep 2022 20:40:39 +0000 Subject: [PATCH] func_strings: Add trim functions. Adds TRIM, LTRIM, and RTRIM, which can be used for trimming leading and trailing whitespace from strings. ASTERISK-30222 #close Change-Id: I50fb0c40726d044a7a41939fa9026f3da4872554 --- doc/CHANGES-staging/func_strings_trim.txt | 5 + funcs/func_strings.c | 186 +++++++++++++++++++++- 2 files changed, 190 insertions(+), 1 deletion(-) create mode 100644 doc/CHANGES-staging/func_strings_trim.txt diff --git a/doc/CHANGES-staging/func_strings_trim.txt b/doc/CHANGES-staging/func_strings_trim.txt new file mode 100644 index 0000000000..ade7a4b61e --- /dev/null +++ b/doc/CHANGES-staging/func_strings_trim.txt @@ -0,0 +1,5 @@ +Subject: func_strings + +Three new functions, TRIM, LTRIM, and RTRIM, are +now available for trimming leading and trailing +whitespace. diff --git a/funcs/func_strings.c b/funcs/func_strings.c index 77cdc99f28..598e6a47b2 100644 --- a/funcs/func_strings.c +++ b/funcs/func_strings.c @@ -4,7 +4,7 @@ * Copyright (C) 2005-2006, Digium, Inc. * Portions Copyright (C) 2005, Tilghman Lesher. All rights reserved. * Portions Copyright (C) 2005, Anthony Minessale II - * Portions Copyright (C) 2021, Naveen Albert + * Portions Copyright (C) 2021, 2022, Naveen Albert * * See http://www.asterisk.org for more information about * the Asterisk project. Please do not directly contact @@ -183,6 +183,51 @@ AST_THREADSTORAGE(tmp_buf); + + + Trim leading and trailing whitespace in a string + + + + + + Replaces all leading and trailing whitespace in the provided string. + + + LTRIM + RTRIM + + + + + Trim leading whitespace in a string + + + + + + Replaces all leading whitespace in the provided string. + + + TRIM + RTRIM + + + + + Trim trailing whitespace in a string + + + + + + Replaces all trailing whitespace in the provided string. + + + TRIM + LTRIM + + Pass the given argument back as a value. @@ -1045,6 +1090,84 @@ static struct ast_custom_function strbetween_function = { .read2 = strbetween, }; +#define ltrim(s) while (isspace(*s)) s++; +#define rtrim(s) { \ + if (s) { \ + char *back = s + strlen(s); \ + while (back != s && isspace(*--back)); \ + if (*s) { \ + *(back + 1) = '\0'; \ + } \ + } \ +} + +static int function_trim(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len) +{ + char *c; + + if (ast_strlen_zero(data)) { + return -1; + } + + c = ast_strdupa(data); + ltrim(c); + rtrim(c); + + ast_copy_string(buf, c, len); + + return 0; +} + +static int function_ltrim(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len) +{ + char *c; + + if (ast_strlen_zero(data)) { + return -1; + } + + c = data; + ltrim(c); + + ast_copy_string(buf, c, len); + + return 0; +} + +static int function_rtrim(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len) +{ + char *c; + + if (ast_strlen_zero(data)) { + return -1; + } + + c = ast_strdupa(data); + rtrim(c); + + ast_copy_string(buf, c, len); + + return 0; +} + +#undef ltrim +#undef rtrim + +static struct ast_custom_function trim_function = { + .name = "TRIM", + .read = function_trim, +}; + +static struct ast_custom_function ltrim_function = { + .name = "LTRIM", + .read = function_ltrim, +}; + +static struct ast_custom_function rtrim_function = { + .name = "RTRIM", + .read = function_rtrim, +}; + static int regex(struct ast_channel *chan, const char *cmd, char *parse, char *buf, size_t len) { @@ -2126,6 +2249,59 @@ AST_TEST_DEFINE(test_STRBETWEEN) return res; } + +AST_TEST_DEFINE(test_TRIM) +{ + int i, res = AST_TEST_PASS; + struct ast_channel *chan; /* dummy channel */ + struct ast_str *str; /* fancy string for holding comparing value */ + + const char *test_strings[][5] = { + {"TRIM", " abcd ", "abcd"}, + {"LTRIM", " abcd ", "abcd "}, + {"RTRIM", " abcd ", " abcd"}, + {"TRIM", "abcd", "abcd"}, + {"TRIM", " a b c d ", "a b c d"}, + }; + + switch (cmd) { + case TEST_INIT: + info->name = "func_TRIM"; + info->category = "/funcs/func_strings/"; + info->summary = "Test TRIM functions"; + info->description = "Verify TRIM behavior"; + return AST_TEST_NOT_RUN; + case TEST_EXECUTE: + break; + } + + if (!(chan = ast_dummy_channel_alloc())) { + ast_test_status_update(test, "Unable to allocate dummy channel\n"); + return AST_TEST_FAIL; + } + + if (!(str = ast_str_create(64))) { + ast_test_status_update(test, "Unable to allocate dynamic string buffer\n"); + ast_channel_release(chan); + return AST_TEST_FAIL; + } + + for (i = 0; i < ARRAY_LEN(test_strings); i++) { + char tmp[512], tmp2[512] = ""; + + snprintf(tmp, sizeof(tmp), "${%s(%s)}", test_strings[i][0], test_strings[i][1]); + ast_str_substitute_variables(&str, 0, chan, tmp); + if (strcmp(test_strings[i][2], ast_str_buffer(str))) { + ast_test_status_update(test, "Format string '%s' substituted to '%s'. Expected '%s'.\n", test_strings[i][0], tmp2, test_strings[i][2]); + res = AST_TEST_FAIL; + } + } + + ast_free(str); + ast_channel_release(chan); + + return res; +} #endif static int unload_module(void) @@ -2137,6 +2313,7 @@ static int unload_module(void) AST_TEST_UNREGISTER(test_FILTER); AST_TEST_UNREGISTER(test_STRREPLACE); AST_TEST_UNREGISTER(test_STRBETWEEN); + AST_TEST_UNREGISTER(test_TRIM); res |= ast_custom_function_unregister(&fieldqty_function); res |= ast_custom_function_unregister(&fieldnum_function); res |= ast_custom_function_unregister(&filter_function); @@ -2163,6 +2340,9 @@ static int unload_module(void) res |= ast_custom_function_unregister(&push_function); res |= ast_custom_function_unregister(&unshift_function); res |= ast_custom_function_unregister(&passthru_function); + res |= ast_custom_function_unregister(&trim_function); + res |= ast_custom_function_unregister(<rim_function); + res |= ast_custom_function_unregister(&rtrim_function); return res; } @@ -2176,6 +2356,7 @@ static int load_module(void) AST_TEST_REGISTER(test_FILTER); AST_TEST_REGISTER(test_STRREPLACE); AST_TEST_REGISTER(test_STRBETWEEN); + AST_TEST_REGISTER(test_TRIM); res |= ast_custom_function_register(&fieldqty_function); res |= ast_custom_function_register(&fieldnum_function); res |= ast_custom_function_register(&filter_function); @@ -2202,6 +2383,9 @@ static int load_module(void) res |= ast_custom_function_register(&push_function); res |= ast_custom_function_register(&unshift_function); res |= ast_custom_function_register(&passthru_function); + res |= ast_custom_function_register(&trim_function); + res |= ast_custom_function_register(<rim_function); + res |= ast_custom_function_register(&rtrim_function); return res; }