strbuf.c 7.9 KB
Newer Older
1
#include "cache.h"
2
#include "refs.h"
3

J
Junio C Hamano 已提交
4 5 6 7 8 9 10 11 12
int prefixcmp(const char *str, const char *prefix)
{
	for (; ; str++, prefix++)
		if (!*prefix)
			return 0;
		else if (*str != *prefix)
			return (unsigned char)*prefix - (unsigned char)*str;
}

A
Avery Pennarun 已提交
13 14 15 16 17 18 19 20 21
int suffixcmp(const char *str, const char *suffix)
{
	int len = strlen(str), suflen = strlen(suffix);
	if (len < suflen)
		return -1;
	else
		return strcmp(str + len - suflen, suffix);
}

22 23 24 25 26 27 28
/*
 * Used as the default ->buf value, so that people can always assume
 * buf is non NULL and ->buf is NUL terminated even for a freshly
 * initialized strbuf.
 */
char strbuf_slopbuf[1];

29 30
void strbuf_init(struct strbuf *sb, size_t hint)
{
31 32
	sb->alloc = sb->len = 0;
	sb->buf = strbuf_slopbuf;
33
	if (hint)
34
		strbuf_grow(sb, hint);
35 36
}

37 38
void strbuf_release(struct strbuf *sb)
{
39 40 41 42
	if (sb->alloc) {
		free(sb->buf);
		strbuf_init(sb, 0);
	}
43 44
}

45
char *strbuf_detach(struct strbuf *sb, size_t *sz)
46
{
47 48 49
	char *res = sb->alloc ? sb->buf : NULL;
	if (sz)
		*sz = sb->len;
50
	strbuf_init(sb, 0);
51 52 53
	return res;
}

54 55 56 57 58 59 60 61 62 63 64 65
void strbuf_attach(struct strbuf *sb, void *buf, size_t len, size_t alloc)
{
	strbuf_release(sb);
	sb->buf   = buf;
	sb->len   = len;
	sb->alloc = alloc;
	strbuf_grow(sb, 0);
	sb->buf[sb->len] = '\0';
}

void strbuf_grow(struct strbuf *sb, size_t extra)
{
66
	int new_buf = !sb->alloc;
67 68
	if (unsigned_add_overflows(extra, 1) ||
	    unsigned_add_overflows(sb->len, extra + 1))
69
		die("you want to use way too much memory");
70
	if (new_buf)
71
		sb->buf = NULL;
72
	ALLOC_GROW(sb->buf, sb->len + extra + 1, sb->alloc);
73 74
	if (new_buf)
		sb->buf[0] = '\0';
75 76
}

77 78 79 80 81 82 83 84 85 86 87 88
void strbuf_trim(struct strbuf *sb)
{
	char *b = sb->buf;
	while (sb->len > 0 && isspace((unsigned char)sb->buf[sb->len - 1]))
		sb->len--;
	while (sb->len > 0 && isspace(*b)) {
		b++;
		sb->len--;
	}
	memmove(sb->buf, b, sb->len);
	sb->buf[sb->len] = '\0';
}
89 90 91 92 93 94 95
void strbuf_rtrim(struct strbuf *sb)
{
	while (sb->len > 0 && isspace((unsigned char)sb->buf[sb->len - 1]))
		sb->len--;
	sb->buf[sb->len] = '\0';
}

96 97 98 99 100 101 102 103 104 105 106
void strbuf_ltrim(struct strbuf *sb)
{
	char *b = sb->buf;
	while (sb->len > 0 && isspace(*b)) {
		b++;
		sb->len--;
	}
	memmove(sb->buf, b, sb->len);
	sb->buf[sb->len] = '\0';
}

107
struct strbuf **strbuf_split_buf(const char *str, size_t slen, int delim, int max)
108 109
{
	int alloc = 2, pos = 0;
110
	const char *n, *p;
111 112 113 114
	struct strbuf **ret;
	struct strbuf *t;

	ret = xcalloc(alloc, sizeof(struct strbuf *));
115 116
	p = n = str;
	while (n < str + slen) {
117
		int len;
J
Jeff King 已提交
118
		if (max <= 0 || pos + 1 < max)
119
			n = memchr(n, delim, slen - (n - str));
J
Jeff King 已提交
120 121
		else
			n = NULL;
122 123 124 125 126
		if (pos + 1 >= alloc) {
			alloc = alloc * 2;
			ret = xrealloc(ret, sizeof(struct strbuf *) * alloc);
		}
		if (!n)
127
			n = str + slen - 1;
128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149
		len = n - p + 1;
		t = xmalloc(sizeof(struct strbuf));
		strbuf_init(t, len);
		strbuf_add(t, p, len);
		ret[pos] = t;
		ret[++pos] = NULL;
		p = ++n;
	}
	return ret;
}

void strbuf_list_free(struct strbuf **sbs)
{
	struct strbuf **s = sbs;

	while (*s) {
		strbuf_release(*s);
		free(*s++);
	}
	free(sbs);
}

150
int strbuf_cmp(const struct strbuf *a, const struct strbuf *b)
P
Pierre Habouzit 已提交
151
{
A
Alex Riesen 已提交
152 153 154 155 156
	int len = a->len < b->len ? a->len: b->len;
	int cmp = memcmp(a->buf, b->buf, len);
	if (cmp)
		return cmp;
	return a->len < b->len ? -1: a->len != b->len;
P
Pierre Habouzit 已提交
157 158
}

159 160 161
void strbuf_splice(struct strbuf *sb, size_t pos, size_t len,
				   const void *data, size_t dlen)
{
162
	if (unsigned_add_overflows(pos, len))
163 164 165 166 167 168 169 170 171 172 173 174 175 176 177
		die("you want to use way too much memory");
	if (pos > sb->len)
		die("`pos' is too far after the end of the buffer");
	if (pos + len > sb->len)
		die("`pos + len' is too far after the end of the buffer");

	if (dlen >= len)
		strbuf_grow(sb, dlen - len);
	memmove(sb->buf + pos + dlen,
			sb->buf + pos + len,
			sb->len - pos - len);
	memcpy(sb->buf + pos, data, dlen);
	strbuf_setlen(sb, sb->len + dlen - len);
}

178 179 180 181 182 183 184 185 186 187
void strbuf_insert(struct strbuf *sb, size_t pos, const void *data, size_t len)
{
	strbuf_splice(sb, pos, 0, data, len);
}

void strbuf_remove(struct strbuf *sb, size_t pos, size_t len)
{
	strbuf_splice(sb, pos, len, NULL, 0);
}

188 189
void strbuf_add(struct strbuf *sb, const void *data, size_t len)
{
190 191 192 193 194
	strbuf_grow(sb, len);
	memcpy(sb->buf + sb->len, data, len);
	strbuf_setlen(sb, sb->len + len);
}

R
René Scharfe 已提交
195 196 197 198 199 200 201
void strbuf_adddup(struct strbuf *sb, size_t pos, size_t len)
{
	strbuf_grow(sb, len);
	memcpy(sb->buf + sb->len, sb->buf + pos, len);
	strbuf_setlen(sb, sb->len + len);
}

202 203
void strbuf_addf(struct strbuf *sb, const char *fmt, ...)
{
204
	va_list ap;
J
Jeff King 已提交
205 206 207 208 209 210 211 212 213
	va_start(ap, fmt);
	strbuf_vaddf(sb, fmt, ap);
	va_end(ap);
}

void strbuf_vaddf(struct strbuf *sb, const char *fmt, va_list ap)
{
	int len;
	va_list cp;
214

215 216
	if (!strbuf_avail(sb))
		strbuf_grow(sb, 64);
J
Jeff King 已提交
217 218 219
	va_copy(cp, ap);
	len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, cp);
	va_end(cp);
220
	if (len < 0)
J
Jeff King 已提交
221
		die("BUG: your vsnprintf is broken (returned %d)", len);
222
	if (len > strbuf_avail(sb)) {
223 224
		strbuf_grow(sb, len);
		len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap);
J
Jeff King 已提交
225 226
		if (len > strbuf_avail(sb))
			die("BUG: your vsnprintf is broken (insatiable)");
227 228
	}
	strbuf_setlen(sb, sb->len + len);
229 230
}

231 232
void strbuf_expand(struct strbuf *sb, const char *format, expand_fn_t fn,
		   void *context)
233 234
{
	for (;;) {
235 236
		const char *percent;
		size_t consumed;
237 238 239 240 241 242 243

		percent = strchrnul(format, '%');
		strbuf_add(sb, format, percent - format);
		if (!*percent)
			break;
		format = percent + 1;

J
Jeff King 已提交
244 245 246 247 248 249
		if (*format == '%') {
			strbuf_addch(sb, '%');
			format++;
			continue;
		}

250 251 252 253
		consumed = fn(sb, format, context);
		if (consumed)
			format += consumed;
		else
254 255 256 257
			strbuf_addch(sb, '%');
	}
}

258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273
size_t strbuf_expand_dict_cb(struct strbuf *sb, const char *placeholder,
		void *context)
{
	struct strbuf_expand_dict_entry *e = context;
	size_t len;

	for (; e->placeholder && (len = strlen(e->placeholder)); e++) {
		if (!strncmp(placeholder, e->placeholder, len)) {
			if (e->value)
				strbuf_addstr(sb, e->value);
			return len;
		}
	}
	return 0;
}

274 275 276 277 278 279 280 281 282 283 284
void strbuf_addbuf_percentquote(struct strbuf *dst, const struct strbuf *src)
{
	int i, len = src->len;

	for (i = 0; i < len; i++) {
		if (src->buf[i] == '%')
			strbuf_addch(dst, '%');
		strbuf_addch(dst, src->buf[i]);
	}
}

285 286
size_t strbuf_fread(struct strbuf *sb, size_t size, FILE *f)
{
287
	size_t res;
288
	size_t oldalloc = sb->alloc;
289 290 291

	strbuf_grow(sb, size);
	res = fread(sb->buf + sb->len, 1, size, f);
292
	if (res > 0)
293
		strbuf_setlen(sb, sb->len + res);
294
	else if (oldalloc == 0)
295
		strbuf_release(sb);
296
	return res;
297 298
}

299
ssize_t strbuf_read(struct strbuf *sb, int fd, size_t hint)
300 301
{
	size_t oldlen = sb->len;
302
	size_t oldalloc = sb->alloc;
303

304
	strbuf_grow(sb, hint ? hint : 8192);
305 306 307 308 309
	for (;;) {
		ssize_t cnt;

		cnt = xread(fd, sb->buf + sb->len, sb->alloc - sb->len - 1);
		if (cnt < 0) {
310 311 312 313
			if (oldalloc == 0)
				strbuf_release(sb);
			else
				strbuf_setlen(sb, oldlen);
314 315 316 317 318
			return -1;
		}
		if (!cnt)
			break;
		sb->len += cnt;
319
		strbuf_grow(sb, 8192);
320 321 322 323
	}

	sb->buf[sb->len] = '\0';
	return sb->len - oldlen;
324 325
}

326 327 328 329
#define STRBUF_MAXLINK (2*PATH_MAX)

int strbuf_readlink(struct strbuf *sb, const char *path, size_t hint)
{
330 331
	size_t oldalloc = sb->alloc;

332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350
	if (hint < 32)
		hint = 32;

	while (hint < STRBUF_MAXLINK) {
		int len;

		strbuf_grow(sb, hint);
		len = readlink(path, sb->buf, hint);
		if (len < 0) {
			if (errno != ERANGE)
				break;
		} else if (len < hint) {
			strbuf_setlen(sb, len);
			return 0;
		}

		/* .. the buffer was too small - try again */
		hint *= 2;
	}
351 352
	if (oldalloc == 0)
		strbuf_release(sb);
353 354 355
	return -1;
}

356
int strbuf_getwholeline(struct strbuf *sb, FILE *fp, int term)
357
{
358
	int ch;
359 360 361

	if (feof(fp))
		return EOF;
362 363

	strbuf_reset(sb);
364
	while ((ch = fgetc(fp)) != EOF) {
365 366
		strbuf_grow(sb, 1);
		sb->buf[sb->len++] = ch;
367 368
		if (ch == term)
			break;
369
	}
370 371
	if (ch == EOF && sb->len == 0)
		return EOF;
372 373

	sb->buf[sb->len] = '\0';
374
	return 0;
375
}
K
Kristian Høgsberg 已提交
376

377 378 379 380 381 382 383 384 385
int strbuf_getline(struct strbuf *sb, FILE *fp, int term)
{
	if (strbuf_getwholeline(sb, fp, term))
		return EOF;
	if (sb->buf[sb->len-1] == term)
		strbuf_setlen(sb, sb->len-1);
	return 0;
}

386
int strbuf_read_file(struct strbuf *sb, const char *path, size_t hint)
K
Kristian Høgsberg 已提交
387 388 389 390 391 392
{
	int fd, len;

	fd = open(path, O_RDONLY);
	if (fd < 0)
		return -1;
393
	len = strbuf_read(sb, fd, hint);
K
Kristian Høgsberg 已提交
394 395 396 397 398 399
	close(fd);
	if (len < 0)
		return -1;

	return len;
}