mirror of
https://github.com/git/git.git
synced 2024-11-30 13:33:44 +08:00
ce68178a0a
This function differs from `strvec_push()` in that it takes ownership of the allocated string that is passed as second argument. This is useful when appending elements to the string array that have been freshly allocated and serve no further other purpose after that. Without declaring this function globally, call sites would allocate the memory, only to have `strvec_push()` duplicate the string, and then the first copy would need to be released. Having this function globally avoids that kind of unnecessary work. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
129 lines
2.5 KiB
C
129 lines
2.5 KiB
C
#include "git-compat-util.h"
|
|
#include "strvec.h"
|
|
#include "strbuf.h"
|
|
|
|
const char *empty_strvec[] = { NULL };
|
|
|
|
void strvec_init(struct strvec *array)
|
|
{
|
|
struct strvec blank = STRVEC_INIT;
|
|
memcpy(array, &blank, sizeof(*array));
|
|
}
|
|
|
|
void strvec_push_nodup(struct strvec *array, char *value)
|
|
{
|
|
if (array->v == empty_strvec)
|
|
array->v = NULL;
|
|
|
|
ALLOC_GROW(array->v, array->nr + 2, array->alloc);
|
|
array->v[array->nr++] = value;
|
|
array->v[array->nr] = NULL;
|
|
}
|
|
|
|
const char *strvec_push(struct strvec *array, const char *value)
|
|
{
|
|
strvec_push_nodup(array, xstrdup(value));
|
|
return array->v[array->nr - 1];
|
|
}
|
|
|
|
const char *strvec_pushf(struct strvec *array, const char *fmt, ...)
|
|
{
|
|
va_list ap;
|
|
struct strbuf v = STRBUF_INIT;
|
|
|
|
va_start(ap, fmt);
|
|
strbuf_vaddf(&v, fmt, ap);
|
|
va_end(ap);
|
|
|
|
strvec_push_nodup(array, strbuf_detach(&v, NULL));
|
|
return array->v[array->nr - 1];
|
|
}
|
|
|
|
void strvec_pushl(struct strvec *array, ...)
|
|
{
|
|
va_list ap;
|
|
const char *arg;
|
|
|
|
va_start(ap, array);
|
|
while ((arg = va_arg(ap, const char *)))
|
|
strvec_push(array, arg);
|
|
va_end(ap);
|
|
}
|
|
|
|
void strvec_pushv(struct strvec *array, const char **items)
|
|
{
|
|
for (; *items; items++)
|
|
strvec_push(array, *items);
|
|
}
|
|
|
|
const char *strvec_replace(struct strvec *array, size_t idx, const char *replacement)
|
|
{
|
|
char *to_free;
|
|
if (idx >= array->nr)
|
|
BUG("index outside of array boundary");
|
|
to_free = (char *) array->v[idx];
|
|
array->v[idx] = xstrdup(replacement);
|
|
free(to_free);
|
|
return array->v[idx];
|
|
}
|
|
|
|
void strvec_remove(struct strvec *array, size_t idx)
|
|
{
|
|
if (idx >= array->nr)
|
|
BUG("index outside of array boundary");
|
|
free((char *)array->v[idx]);
|
|
memmove(array->v + idx, array->v + idx + 1, (array->nr - idx) * sizeof(char *));
|
|
array->nr--;
|
|
}
|
|
|
|
void strvec_pop(struct strvec *array)
|
|
{
|
|
if (!array->nr)
|
|
return;
|
|
free((char *)array->v[array->nr - 1]);
|
|
array->v[array->nr - 1] = NULL;
|
|
array->nr--;
|
|
}
|
|
|
|
void strvec_split(struct strvec *array, const char *to_split)
|
|
{
|
|
while (isspace(*to_split))
|
|
to_split++;
|
|
for (;;) {
|
|
const char *p = to_split;
|
|
|
|
if (!*p)
|
|
break;
|
|
|
|
while (*p && !isspace(*p))
|
|
p++;
|
|
strvec_push_nodup(array, xstrndup(to_split, p - to_split));
|
|
|
|
while (isspace(*p))
|
|
p++;
|
|
to_split = p;
|
|
}
|
|
}
|
|
|
|
void strvec_clear(struct strvec *array)
|
|
{
|
|
if (array->v != empty_strvec) {
|
|
int i;
|
|
for (i = 0; i < array->nr; i++)
|
|
free((char *)array->v[i]);
|
|
free(array->v);
|
|
}
|
|
strvec_init(array);
|
|
}
|
|
|
|
const char **strvec_detach(struct strvec *array)
|
|
{
|
|
if (array->v == empty_strvec)
|
|
return xcalloc(1, sizeof(const char *));
|
|
else {
|
|
const char **ret = array->v;
|
|
strvec_init(array);
|
|
return ret;
|
|
}
|
|
}
|