4
4
* Copyright (C) 2005-2006, Digium, Inc.
5
5
* Portions Copyright (C) 2005, Tilghman Lesher. All rights reserved.
6
6
* Portions Copyright (C) 2005, Anthony Minessale II
7
+ * Portions Copyright (C) 2021, Naveen Albert
7
8
*
8
9
* See http://www.asterisk.org for more information about
9
10
* the Asterisk project. Please do not directly contact
22
23
*
23
24
* \author Tilghman Lesher
24
25
* \author Anothony Minessale II
26
+ * \author Naveen Albert
25
27
* \ingroup functions
26
28
*/
27
29
@@ -152,6 +154,24 @@ AST_THREADSTORAGE(tmp_buf);
152
154
<note><para>The replacement only occurs in the output. The original variable is not altered.</para></note>
153
155
</description>
154
156
</function>
157
+ <function name="STRBETWEEN" language="en_US">
158
+ <synopsis>
159
+ Inserts a substring between each character in a string.
160
+ </synopsis>
161
+ <syntax>
162
+ <parameter name="varname" required="true" />
163
+ <parameter name="insert-string" required="true" />
164
+ </syntax>
165
+ <description>
166
+ <para>Inserts a substring <replaceable>find-string</replaceable> between each character in
167
+ <replaceable>varname</replaceable>.</para>
168
+ <note><para>The replacement only occurs in the output. The original variable is not altered.</para></note>
169
+ <example title="Add half-second pause between dialed digits">
170
+ same => n,Set(digits=5551212)
171
+ same => n,SendDTMF(${STRBETWEEN(digits,w)) ; this will send 5w5w5w1w2w1w2
172
+ </example>
173
+ </description>
174
+ </function>
155
175
<function name="PASSTHRU" language="en_US">
156
176
<synopsis>
157
177
Pass the given argument back as a value.
@@ -945,6 +965,53 @@ static struct ast_custom_function strreplace_function = {
945
965
.read2 = strreplace ,
946
966
};
947
967
968
+ static int strbetween (struct ast_channel * chan , const char * cmd , char * data , struct ast_str * * buf , ssize_t len )
969
+ {
970
+ int c , origsize ;
971
+ char * varsubstr , * origstr ;
972
+ struct ast_str * str = ast_str_thread_get (& result_buf , 16 ); /* Holds the data obtained from varname */
973
+
974
+ AST_DECLARE_APP_ARGS (args ,
975
+ AST_APP_ARG (varname );
976
+ AST_APP_ARG (insert_string );
977
+ AST_APP_ARG (other ); /* Any remining unused arguments */
978
+ );
979
+
980
+ ast_str_reset (* buf );
981
+
982
+ if (!str ) {
983
+ ast_log (LOG_ERROR , "Couldn't obtain string\n" );
984
+ return -1 ;
985
+ }
986
+
987
+ AST_STANDARD_APP_ARGS (args , data );
988
+
989
+ if (args .argc != 2 || ast_strlen_zero (args .varname )) {
990
+ ast_log (LOG_ERROR , "Usage: %s(<varname>,<insert-string>)\n" , cmd );
991
+ return -1 ;
992
+ }
993
+
994
+ varsubstr = ast_alloca (strlen (args .varname ) + 4 );
995
+ sprintf (varsubstr , "${%s}" , args .varname );
996
+ ast_str_substitute_variables (& str , 0 , chan , varsubstr );
997
+ origstr = ast_str_buffer (str );
998
+ origsize = strlen (origstr );
999
+ for (c = 0 ; c < origsize ; c ++ ) {
1000
+ ast_str_append (buf , len , "%c" , origstr [c ]);
1001
+ /* no insert after the last character */
1002
+ if (c < (origsize - 1 )) {
1003
+ ast_str_append (buf , len , "%s" , args .insert_string );
1004
+ }
1005
+ }
1006
+
1007
+ return 0 ;
1008
+ }
1009
+
1010
+ static struct ast_custom_function strbetween_function = {
1011
+ .name = "STRBETWEEN" ,
1012
+ .read2 = strbetween ,
1013
+ };
1014
+
948
1015
static int regex (struct ast_channel * chan , const char * cmd , char * parse , char * buf ,
949
1016
size_t len )
950
1017
{
@@ -1953,6 +2020,79 @@ AST_TEST_DEFINE(test_STRREPLACE)
1953
2020
1954
2021
return res ;
1955
2022
}
2023
+
2024
+ AST_TEST_DEFINE (test_STRBETWEEN )
2025
+ {
2026
+ int i , res = AST_TEST_PASS ;
2027
+ struct ast_channel * chan ; /* dummy channel */
2028
+ struct ast_str * str ; /* fancy string for holding comparing value */
2029
+
2030
+ const char * test_strings [][5 ] = {
2031
+ {"0" , "w" , "0" },
2032
+ {"30" , "w" , "3w0" },
2033
+ {"212" , "w" , "2w1w2" },
2034
+ {"212" , "55" , "2551552" },
2035
+ {"212" , " " , "2 1 2" },
2036
+ {"" , "w" , "" },
2037
+ {"555" , "" , "555" },
2038
+ {"abcdefg" , "_" , "a_b_c_d_e_f_g" },
2039
+ {"A" , "A" , "A" },
2040
+ {"AA" , "B" , "ABA" },
2041
+ {"AAA" , "B" , "ABABA" },
2042
+ };
2043
+
2044
+ switch (cmd ) {
2045
+ case TEST_INIT :
2046
+ info -> name = "func_STRBETWEEN" ;
2047
+ info -> category = "/funcs/func_strings/" ;
2048
+ info -> summary = "Test STRBETWEEN function" ;
2049
+ info -> description = "Verify STRBETWEEN behavior" ;
2050
+ return AST_TEST_NOT_RUN ;
2051
+ case TEST_EXECUTE :
2052
+ break ;
2053
+ }
2054
+
2055
+ if (!(chan = ast_dummy_channel_alloc ())) {
2056
+ ast_test_status_update (test , "Unable to allocate dummy channel\n" );
2057
+ return AST_TEST_FAIL ;
2058
+ }
2059
+
2060
+ if (!(str = ast_str_create (64 ))) {
2061
+ ast_test_status_update (test , "Unable to allocate dynamic string buffer\n" );
2062
+ ast_channel_release (chan );
2063
+ return AST_TEST_FAIL ;
2064
+ }
2065
+
2066
+ for (i = 0 ; i < ARRAY_LEN (test_strings ); i ++ ) {
2067
+ char tmp [512 ], tmp2 [512 ] = "" ;
2068
+
2069
+ struct ast_var_t * var = ast_var_assign ("test_string" , test_strings [i ][0 ]);
2070
+ if (!var ) {
2071
+ ast_test_status_update (test , "Unable to allocate variable\n" );
2072
+ ast_free (str );
2073
+ ast_channel_release (chan );
2074
+ return AST_TEST_FAIL ;
2075
+ }
2076
+
2077
+ AST_LIST_INSERT_HEAD (ast_channel_varshead (chan ), var , entries );
2078
+
2079
+ if (test_strings [i ][1 ]) {
2080
+ snprintf (tmp , sizeof (tmp ), "${STRBETWEEN(%s,%s)}" , "test_string" , test_strings [i ][1 ]);
2081
+ } else {
2082
+ snprintf (tmp , sizeof (tmp ), "${STRBETWEEN(%s)}" , "test_string" );
2083
+ }
2084
+ ast_str_substitute_variables (& str , 0 , chan , tmp );
2085
+ if (strcmp (test_strings [i ][2 ], ast_str_buffer (str ))) {
2086
+ ast_test_status_update (test , "Format string '%s' substituted to '%s'. Expected '%s'.\n" , test_strings [i ][0 ], tmp2 , test_strings [i ][2 ]);
2087
+ res = AST_TEST_FAIL ;
2088
+ }
2089
+ }
2090
+
2091
+ ast_free (str );
2092
+ ast_channel_release (chan );
2093
+
2094
+ return res ;
2095
+ }
1956
2096
#endif
1957
2097
1958
2098
static int unload_module (void )
@@ -1963,11 +2103,13 @@ static int unload_module(void)
1963
2103
AST_TEST_UNREGISTER (test_REPLACE );
1964
2104
AST_TEST_UNREGISTER (test_FILTER );
1965
2105
AST_TEST_UNREGISTER (test_STRREPLACE );
2106
+ AST_TEST_UNREGISTER (test_STRBETWEEN );
1966
2107
res |= ast_custom_function_unregister (& fieldqty_function );
1967
2108
res |= ast_custom_function_unregister (& fieldnum_function );
1968
2109
res |= ast_custom_function_unregister (& filter_function );
1969
2110
res |= ast_custom_function_unregister (& replace_function );
1970
2111
res |= ast_custom_function_unregister (& strreplace_function );
2112
+ res |= ast_custom_function_unregister (& strbetween_function );
1971
2113
res |= ast_custom_function_unregister (& listfilter_function );
1972
2114
res |= ast_custom_function_unregister (& regex_function );
1973
2115
res |= ast_custom_function_unregister (& array_function );
@@ -2000,11 +2142,13 @@ static int load_module(void)
2000
2142
AST_TEST_REGISTER (test_REPLACE );
2001
2143
AST_TEST_REGISTER (test_FILTER );
2002
2144
AST_TEST_REGISTER (test_STRREPLACE );
2145
+ AST_TEST_REGISTER (test_STRBETWEEN );
2003
2146
res |= ast_custom_function_register (& fieldqty_function );
2004
2147
res |= ast_custom_function_register (& fieldnum_function );
2005
2148
res |= ast_custom_function_register (& filter_function );
2006
2149
res |= ast_custom_function_register (& replace_function );
2007
2150
res |= ast_custom_function_register (& strreplace_function );
2151
+ res |= ast_custom_function_register (& strbetween_function );
2008
2152
res |= ast_custom_function_register (& listfilter_function );
2009
2153
res |= ast_custom_function_register (& regex_function );
2010
2154
res |= ast_custom_function_register (& array_function );
0 commit comments