From 4ea517a6e07f47117348c68c6fe087bf6d401558 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 16 Feb 2023 15:41:55 +0100 Subject: [PATCH] strv: add strv_copy_n() helper for copying part of a n strv Conflict:Context Adaptation. Test case adaptation. Reference:https://github.com/systemd/systemd/commit/4ea517a6e07f47117348c68c6fe087bf6d401558 --- src/basic/strv.c | 10 ++++++++-- src/basic/strv.h | 5 ++++- src/test/test-strv.c | 41 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 53 insertions(+), 3 deletions(-) diff --git a/src/basic/strv.c b/src/basic/strv.c index 6a2e44c..d6c50f5 100644 --- a/src/basic/strv.c +++ b/src/basic/strv.c @@ -88,20 +88,26 @@ char** strv_free_erase(char **l) { return mfree(l); } -char** strv_copy(char * const *l) { +char** strv_copy_n(char * const *l, size_t m) { _cleanup_strv_free_ char **result = NULL; char **k, * const *i; - result = new(char*, strv_length(l) + 1); + result = new(char*, MIN(strv_length(l), m) + 1); if (!result) return NULL; k = result; STRV_FOREACH(i, l) { + if (m == 0) + break; + *k = strdup(*i); if (!*k) return NULL; k++; + + if (m != SIZE_MAX) + m--; } *k = NULL; diff --git a/src/basic/strv.h b/src/basic/strv.h index 8674bfd..108ec25 100644 --- a/src/basic/strv.h +++ b/src/basic/strv.h @@ -29,7 +29,10 @@ char** strv_free_erase(char **l); DEFINE_TRIVIAL_CLEANUP_FUNC(char**, strv_free_erase); #define _cleanup_strv_free_erase_ _cleanup_(strv_free_erasep) -char** strv_copy(char * const *l); +char** strv_copy_n(char * const *l, size_t n); +static inline char** strv_copy(char * const *l) { + return strv_copy_n(l, SIZE_MAX); +} size_t strv_length(char * const *l) _pure_; int strv_extend_strv(char ***a, char * const *b, bool filter_duplicates); diff --git a/src/test/test-strv.c b/src/test/test-strv.c index 1345252..dd119a8 100644 --- a/src/test/test-strv.c +++ b/src/test/test-strv.c @@ -988,6 +988,46 @@ static void test_strv_fnmatch(void) { assert(pos == 1); } +static void test_strv_copy_n(void) { + char **x = STRV_MAKE("a", "b", "c", "d", "e"); + _cleanup_strv_free_ char **l = NULL; + + l = strv_copy_n(x, 0); + assert_se(strv_equal(l, NULL)); + strv_free(l); + + l = strv_copy_n(x, 0); + assert_se(strv_equal(l, (char**) { NULL })); + strv_free(l); + + l = strv_copy_n(x, 1); + assert_se(strv_equal(l, STRV_MAKE("a"))); + strv_free(l); + + l = strv_copy_n(x, 2); + assert_se(strv_equal(l, STRV_MAKE("a", "b"))); + strv_free(l); + + l = strv_copy_n(x, 3); + assert_se(strv_equal(l, STRV_MAKE("a", "b", "c"))); + strv_free(l); + + l = strv_copy_n(x, 4); + assert_se(strv_equal(l, STRV_MAKE("a", "b", "c", "d"))); + strv_free(l); + + l = strv_copy_n(x, 5); + assert_se(strv_equal(l, STRV_MAKE("a", "b", "c", "d", "e"))); + strv_free(l); + + l = strv_copy_n(x, 6); + assert_se(strv_equal(l, STRV_MAKE("a", "b", "c", "d", "e"))); + strv_free(l); + + l = strv_copy_n(x, SIZE_MAX); + assert_se(strv_equal(l, STRV_MAKE("a", "b", "c", "d", "e"))); +} + int main(int argc, char *argv[]) { test_str_in_set(); test_strptr_in_set(); @@ -1054,6 +1094,7 @@ int main(int argc, char *argv[]) { test_foreach_string(); test_strv_fnmatch(); + test_strv_copy_n(); return 0; } -- 2.33.0