strvec: introduce new `strvec_splice()` function
Introduce a new `strvec_splice()` function that can replace a range of strings in the vector with another array of strings. This function will be used in subsequent commits. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Patrick Steinhardt committed
Nov 20, 2024 at 14:39 UTC
3f5fadef3718f0ada963aeb25be70c8ba71b5c7c
3 files changed
+93
strvec.c
+19
@@ -56,6 +56,25 @@ void strvec_pushv(struct strvec *array, const char **items)
56
strvec_push(array, *items);
57
}
58
59
+void strvec_splice(struct strvec *array, size_t idx, size_t len,
60
+ const char **replacement, size_t replacement_len)
61
+{
62
+ if (idx + len > array->nr)
63
+ BUG("range outside of array boundary");
64
+ if (replacement_len > len)
65
+ ALLOC_GROW(array->v, array->nr + (replacement_len - len) + 1,
66
+ array->alloc);
67
+ for (size_t i = 0; i < len; i++)
68
+ free((char *)array->v[idx + i]);
69
+ if (replacement_len != len) {
70
+ memmove(array->v + idx + replacement_len, array->v + idx + len,
71
+ (array->nr - idx - len + 1) * sizeof(char *));
72
+ array->nr += (replacement_len - len);
73
+ }
74
+ for (size_t i = 0; i < replacement_len; i++)
75
+ array->v[idx + i] = xstrdup(replacement[i]);
76
+}
77
+
78
const char *strvec_replace(struct strvec *array, size_t idx, const char *replacement)
79
{
80
char *to_free;
strvec.h
+9
@@ -67,6 +67,15 @@ void strvec_pushl(struct strvec *, ...);
67
/* Push a null-terminated array of strings onto the end of the array. */
68
void strvec_pushv(struct strvec *, const char **);
69
70
+/*
71
+ * Replace `len` values starting at `idx` with the provided replacement
72
+ * strings. If `len` is zero this is effectively an insert at the given `idx`.
73
+ * If `replacement_len` is zero this is effectively a delete of `len` items
74
+ * starting at `idx`.
75
+ */
76
+void strvec_splice(struct strvec *array, size_t idx, size_t len,
77
+ const char **replacement, size_t replacement_len);
78
+
79
/**
80
* Replace the value at the given index with a new value. The index must be
81
* valid. Returns a pointer to the inserted value.
t/unit-tests/strvec.c
+65
@@ -88,6 +88,71 @@ void test_strvec__pushv(void)
88
strvec_clear(&vec);
89
}
90
91
+void test_strvec__splice_with_same_size_replacement(void)
92
+{
93
+ struct strvec vec = STRVEC_INIT;
94
+ const char *replacement[] = { "1" };
95
+
96
+ strvec_pushl(&vec, "foo", "bar", "baz", NULL);
97
+ strvec_splice(&vec, 1, 1, replacement, ARRAY_SIZE(replacement));
98
+ check_strvec(&vec, "foo", "1", "baz", NULL);
99
+ strvec_clear(&vec);
100
+}
101
+
102
+void test_strvec__splice_with_smaller_replacement(void)
103
+{
104
+ struct strvec vec = STRVEC_INIT;
105
+ const char *replacement[] = { "1" };
106
+
107
+ strvec_pushl(&vec, "foo", "bar", "baz", NULL);
108
+ strvec_splice(&vec, 1, 2, replacement, ARRAY_SIZE(replacement));
109
+ check_strvec(&vec, "foo", "1", NULL);
110
+ strvec_clear(&vec);
111
+}
112
+
113
+void test_strvec__splice_with_bigger_replacement(void)
114
+{
115
+ struct strvec vec = STRVEC_INIT;
116
+ const char *replacement[] = { "1", "2", "3" };
117
+
118
+ strvec_pushl(&vec, "foo", "bar", "baz", NULL);
119
+ strvec_splice(&vec, 0, 2, replacement, ARRAY_SIZE(replacement));
120
+ check_strvec(&vec, "1", "2", "3", "baz", NULL);
121
+ strvec_clear(&vec);
122
+}
123
+
124
+void test_strvec__splice_with_empty_replacement(void)
125
+{
126
+ struct strvec vec = STRVEC_INIT;
127
+
128
+ strvec_pushl(&vec, "foo", "bar", "baz", NULL);
129
+ strvec_splice(&vec, 0, 2, NULL, 0);
130
+ check_strvec(&vec, "baz", NULL);
131
+ strvec_clear(&vec);
132
+}
133
+
134
+void test_strvec__splice_with_empty_original(void)
135
+{
136
+ struct strvec vec = STRVEC_INIT;
137
+ const char *replacement[] = { "1", "2" };
138
+
139
+ strvec_pushl(&vec, "foo", "bar", "baz", NULL);
140
+ strvec_splice(&vec, 1, 0, replacement, ARRAY_SIZE(replacement));
141
+ check_strvec(&vec, "foo", "1", "2", "bar", "baz", NULL);
142
+ strvec_clear(&vec);
143
+}
144
+
145
+void test_strvec__splice_at_tail(void)
146
+{
147
+ struct strvec vec = STRVEC_INIT;
148
+ const char *replacement[] = { "1", "2" };
149
+
150
+ strvec_pushl(&vec, "foo", "bar", NULL);
151
+ strvec_splice(&vec, 2, 0, replacement, ARRAY_SIZE(replacement));
152
+ check_strvec(&vec, "foo", "bar", "1", "2", NULL);
153
+ strvec_clear(&vec);
154
+}
155
+
156
void test_strvec__replace_at_head(void)
157
{
158
struct strvec vec = STRVEC_INIT;