Git fork
at reftables-rust 149 lines 3.4 kB view raw
1#include "git-compat-util.h" 2#include "strvec.h" 3#include "strbuf.h" 4 5const char *empty_strvec[] = { NULL }; 6 7void strvec_init(struct strvec *array) 8{ 9 struct strvec blank = STRVEC_INIT; 10 memcpy(array, &blank, sizeof(*array)); 11} 12 13void strvec_push_nodup(struct strvec *array, char *value) 14{ 15 if (array->v == empty_strvec) 16 array->v = NULL; 17 18 ALLOC_GROW(array->v, array->nr + 2, array->alloc); 19 array->v[array->nr++] = value; 20 array->v[array->nr] = NULL; 21} 22 23const char *strvec_push(struct strvec *array, const char *value) 24{ 25 strvec_push_nodup(array, xstrdup(value)); 26 return array->v[array->nr - 1]; 27} 28 29const char *strvec_pushf(struct strvec *array, const char *fmt, ...) 30{ 31 va_list ap; 32 struct strbuf v = STRBUF_INIT; 33 34 va_start(ap, fmt); 35 strbuf_vaddf(&v, fmt, ap); 36 va_end(ap); 37 38 strvec_push_nodup(array, strbuf_detach(&v, NULL)); 39 return array->v[array->nr - 1]; 40} 41 42void strvec_pushl(struct strvec *array, ...) 43{ 44 va_list ap; 45 const char *arg; 46 47 va_start(ap, array); 48 while ((arg = va_arg(ap, const char *))) 49 strvec_push(array, arg); 50 va_end(ap); 51} 52 53void strvec_pushv(struct strvec *array, const char **items) 54{ 55 for (; *items; items++) 56 strvec_push(array, *items); 57} 58 59void 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 if (array->v == empty_strvec) 66 array->v = NULL; 67 ALLOC_GROW(array->v, array->nr + (replacement_len - len) + 1, 68 array->alloc); 69 array->v[array->nr + (replacement_len - len)] = NULL; 70 } 71 for (size_t i = 0; i < len; i++) 72 free((char *)array->v[idx + i]); 73 if ((replacement_len != len) && array->nr) 74 memmove(array->v + idx + replacement_len, array->v + idx + len, 75 (array->nr - idx - len + 1) * sizeof(char *)); 76 array->nr += replacement_len - len; 77 for (size_t i = 0; i < replacement_len; i++) 78 array->v[idx + i] = xstrdup(replacement[i]); 79} 80 81const char *strvec_replace(struct strvec *array, size_t idx, const char *replacement) 82{ 83 char *to_free; 84 if (idx >= array->nr) 85 BUG("index outside of array boundary"); 86 to_free = (char *) array->v[idx]; 87 array->v[idx] = xstrdup(replacement); 88 free(to_free); 89 return array->v[idx]; 90} 91 92void strvec_remove(struct strvec *array, size_t idx) 93{ 94 if (idx >= array->nr) 95 BUG("index outside of array boundary"); 96 free((char *)array->v[idx]); 97 memmove(array->v + idx, array->v + idx + 1, (array->nr - idx) * sizeof(char *)); 98 array->nr--; 99} 100 101void strvec_pop(struct strvec *array) 102{ 103 if (!array->nr) 104 return; 105 free((char *)array->v[array->nr - 1]); 106 array->v[array->nr - 1] = NULL; 107 array->nr--; 108} 109 110void strvec_split(struct strvec *array, const char *to_split) 111{ 112 while (isspace(*to_split)) 113 to_split++; 114 for (;;) { 115 const char *p = to_split; 116 117 if (!*p) 118 break; 119 120 while (*p && !isspace(*p)) 121 p++; 122 strvec_push_nodup(array, xstrndup(to_split, p - to_split)); 123 124 while (isspace(*p)) 125 p++; 126 to_split = p; 127 } 128} 129 130void strvec_clear(struct strvec *array) 131{ 132 if (array->v != empty_strvec) { 133 for (size_t i = 0; i < array->nr; i++) 134 free((char *)array->v[i]); 135 free(array->v); 136 } 137 strvec_init(array); 138} 139 140const char **strvec_detach(struct strvec *array) 141{ 142 if (array->v == empty_strvec) 143 return xcalloc(1, sizeof(const char *)); 144 else { 145 const char **ret = array->v; 146 strvec_init(array); 147 return ret; 148 } 149}