summaryrefslogtreecommitdiffstats
path: root/src/util/argv.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-13 08:41:51 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-13 08:41:51 +0000
commit3e160e27e4686620d16477a9ea9cf00141e52ce7 (patch)
tree884561d26afa36d7653aa4dc43410e1ae479d43e /src/util/argv.c
parentAdding upstream version 3.8.6. (diff)
downloadpostfix-upstream/3.9.0.tar.xz
postfix-upstream/3.9.0.zip
Adding upstream version 3.9.0.upstream/3.9.0
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r--src/util/argv.c57
1 files changed, 56 insertions, 1 deletions
diff --git a/src/util/argv.c b/src/util/argv.c
index 4e05fd0..332426e 100644
--- a/src/util/argv.c
+++ b/src/util/argv.c
@@ -53,6 +53,11 @@
/* ssize_t pos;
/* ssize_t how_many;
/*
+/* char *argv_join(buf, argvp, delim)
+/* VSTRING *buf;
+/* ARGV *argvp;
+/* int delim;
+/*
/* void ARGV_FAKE_BEGIN(argv, arg)
/* const char *arg;
/*
@@ -109,6 +114,10 @@
/* starting at the specified array position. The result is
/* null-terminated.
/*
+/* argv_join() joins all elements in an array using the
+/* specified delimiter value, and appends the result to the
+/* specified buffer.
+/*
/* ARGV_FAKE_BEGIN/END are an optimization for the case where
/* a single string needs to be passed into an ARGV-based
/* interface. ARGV_FAKE_BEGIN() opens a statement block and
@@ -148,6 +157,7 @@
#include "mymalloc.h"
#include "msg.h"
+#include "vstring.h"
#include "argv.h"
#ifdef TEST
@@ -379,6 +389,20 @@ void argv_delete(ARGV *argvp, ssize_t first, ssize_t how_many)
argvp->argc -= how_many;
}
+/* argv_join - concatenate array elements with delimiter */
+
+char *argv_join(VSTRING *buf, ARGV *argv, int delim)
+{
+ char **cpp;
+
+ for (cpp = argv->argv; *cpp; cpp++) {
+ vstring_strcat(buf, *cpp);
+ if (cpp[1])
+ VSTRING_ADDCH(buf, delim);
+ }
+ return (vstring_str(buf));
+}
+
#ifdef TEST
/*
@@ -402,6 +426,7 @@ typedef struct TEST_CASE {
const char *exp_panic_msg; /* expected panic */
int exp_argc; /* expected array length */
const char *exp_argv[ARRAY_LEN]; /* expected array content */
+ int join_delim; /* argv_join() delimiter */
} TEST_CASE;
#define TERMINATE_ARRAY (1)
@@ -559,6 +584,24 @@ static ARGV *test_argv_bad_delete3(const TEST_CASE *tp, ARGV *argvp)
return (argvp);
}
+/* test_argv_join - populate, join, and overwrite */
+
+static ARGV *test_argv_join(const TEST_CASE *tp, ARGV *argvp)
+{
+ VSTRING *buf = vstring_alloc(100);
+
+ /*
+ * Impedance mismatch: argv_join() produces output to VSTRING, but the
+ * test fixture wants output to ARGV.
+ */
+ test_argv_populate(tp, argvp);
+ argv_join(buf, argvp, tp->join_delim);
+ argv_delete(argvp, 0, argvp->argc);
+ argv_add(argvp, vstring_str(buf), ARGV_END);
+ vstring_free(buf);
+ return (argvp);
+}
+
/* test_argv_verify - verify result */
static int test_argv_verify(const TEST_CASE *tp, ARGV *argvp)
@@ -573,7 +616,7 @@ static int test_argv_verify(const TEST_CASE *tp, ARGV *argvp)
}
if (strcmp(vstring_str(test_panic_str), tp->exp_panic_msg) != 0) {
msg_warn("test case '%s': got '%s', want: '%s'",
- tp->label, vstring_str(test_panic_str), tp->exp_panic_msg);
+ tp->label, vstring_str(test_panic_str), tp->exp_panic_msg);
return (FAIL);
}
return (PASS);
@@ -682,6 +725,18 @@ static const TEST_CASE test_cases[] = {
{"foo", "baz", "bar", 0}, 0, test_argv_bad_delete3,
"argv_delete bad range: (start=100 count=1)"
},
+ {"argv_join, multiple strings",
+ {"foo", "baz", "bar", 0}, 0, test_argv_join,
+ 0, 1, {"foo:baz:bar", 0}, ':'
+ },
+ {"argv_join, one string",
+ {"foo", 0}, 0, test_argv_join,
+ 0, 1, {"foo", 0}, ':'
+ },
+ {"argv_join, empty",
+ {0}, 0, test_argv_join,
+ 0, 1, {"", 0}, ':'
+ },
0,
};