strbuf.c 9.7 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;
	strbuf_grow(sb, 0);
	res = sb->buf;
50 51
	if (sz)
		*sz = sb->len;
52
	strbuf_init(sb, 0);
53 54 55
	return res;
}

56 57 58 59 60 61 62 63 64 65 66 67
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)
{
68
	int new_buf = !sb->alloc;
69 70
	if (unsigned_add_overflows(extra, 1) ||
	    unsigned_add_overflows(sb->len, extra + 1))
71
		die("you want to use way too much memory");
72
	if (new_buf)
73
		sb->buf = NULL;
74
	ALLOC_GROW(sb->buf, sb->len + extra + 1, sb->alloc);
75 76
	if (new_buf)
		sb->buf[0] = '\0';
77 78
}

79 80 81 82 83 84 85 86 87 88 89 90
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';
}
91 92 93 94 95 96 97
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';
}

98 99 100 101 102 103 104 105 106 107 108
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';
}

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

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

152
int strbuf_cmp(const struct strbuf *a, const struct strbuf *b)
P
Pierre Habouzit 已提交
153
{
A
Alex Riesen 已提交
154 155 156 157 158
	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 已提交
159 160
}

161 162 163
void strbuf_splice(struct strbuf *sb, size_t pos, size_t len,
				   const void *data, size_t dlen)
{
164
	if (unsigned_add_overflows(pos, len))
165 166 167 168 169 170 171 172 173 174 175 176 177 178 179
		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);
}

180 181 182 183 184 185 186 187 188 189
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);
}

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

R
René Scharfe 已提交
197 198 199 200 201 202 203
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);
}

204 205
void strbuf_addf(struct strbuf *sb, const char *fmt, ...)
{
206
	va_list ap;
J
Jeff King 已提交
207 208 209 210 211 212 213 214 215
	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;
216

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

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

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

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

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

260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275
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;
}

276 277 278 279 280 281 282 283 284 285 286
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]);
	}
}

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

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

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

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

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

	sb->buf[sb->len] = '\0';
	return sb->len - oldlen;
326 327
}

328 329 330 331
#define STRBUF_MAXLINK (2*PATH_MAX)

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

334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352
	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;
	}
353 354
	if (oldalloc == 0)
		strbuf_release(sb);
355 356 357
	return -1;
}

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

	if (feof(fp))
		return EOF;
364 365

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

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

379 380 381 382 383 384 385 386 387
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;
}

388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403
int strbuf_getwholeline_fd(struct strbuf *sb, int fd, int term)
{
	strbuf_reset(sb);

	while (1) {
		char ch;
		ssize_t len = xread(fd, &ch, 1);
		if (len <= 0)
			return EOF;
		strbuf_addch(sb, ch);
		if (ch == term)
			break;
	}
	return 0;
}

404
int strbuf_read_file(struct strbuf *sb, const char *path, size_t hint)
K
Kristian Høgsberg 已提交
405 406 407 408 409 410
{
	int fd, len;

	fd = open(path, O_RDONLY);
	if (fd < 0)
		return -1;
411
	len = strbuf_read(sb, fd, hint);
K
Kristian Høgsberg 已提交
412 413 414 415 416 417
	close(fd);
	if (len < 0)
		return -1;

	return len;
}
418 419 420 421 422 423 424 425 426 427 428 429 430 431

void strbuf_add_lines(struct strbuf *out, const char *prefix,
		      const char *buf, size_t size)
{
	while (size) {
		const char *next = memchr(buf, '\n', size);
		next = next ? (next + 1) : (buf + size);
		strbuf_addstr(out, prefix);
		strbuf_add(out, buf, next - buf);
		size -= next - buf;
		buf = next;
	}
	strbuf_complete_line(out);
}
J
Junio C Hamano 已提交
432

J
Jeff King 已提交
433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449
static int is_rfc3986_reserved(char ch)
{
	switch (ch) {
		case '!': case '*': case '\'': case '(': case ')': case ';':
		case ':': case '@': case '&': case '=': case '+': case '$':
		case ',': case '/': case '?': case '#': case '[': case ']':
			return 1;
	}
	return 0;
}

static int is_rfc3986_unreserved(char ch)
{
	return isalnum(ch) ||
		ch == '-' || ch == '_' || ch == '.' || ch == '~';
}

450 451
static void strbuf_add_urlencode(struct strbuf *sb, const char *s, size_t len,
				 int reserved)
J
Jeff King 已提交
452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468
{
	strbuf_grow(sb, len);
	while (len--) {
		char ch = *s++;
		if (is_rfc3986_unreserved(ch) ||
		    (!reserved && is_rfc3986_reserved(ch)))
			strbuf_addch(sb, ch);
		else
			strbuf_addf(sb, "%%%02x", ch);
	}
}

void strbuf_addstr_urlencode(struct strbuf *sb, const char *s,
			     int reserved)
{
	strbuf_add_urlencode(sb, s, strlen(s), reserved);
}
469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492

int printf_ln(const char *fmt, ...)
{
	int ret;
	va_list ap;
	va_start(ap, fmt);
	ret = vprintf(fmt, ap);
	va_end(ap);
	if (ret < 0 || putchar('\n') == EOF)
		return -1;
	return ret + 1;
}

int fprintf_ln(FILE *fp, const char *fmt, ...)
{
	int ret;
	va_list ap;
	va_start(ap, fmt);
	ret = vfprintf(fp, fmt, ap);
	va_end(ap);
	if (ret < 0 || putc('\n', fp) == EOF)
		return -1;
	return ret + 1;
}