1#include "cache.h"
2#include "refs.h"
3
4int starts_with(const char *str, const char *prefix)
5{
6 for (; ; str++, prefix++)
7 if (!*prefix)
8 return 1;
9 else if (*str != *prefix)
10 return 0;
11}
12
13/*
14 * Used as the default ->buf value, so that people can always assume
15 * buf is non NULL and ->buf is NUL terminated even for a freshly
16 * initialized strbuf.
17 */
18char strbuf_slopbuf[1];
19
20void strbuf_init(struct strbuf *sb, size_t hint)
21{
22 sb->alloc = sb->len = 0;
23 sb->buf = strbuf_slopbuf;
24 if (hint)
25 strbuf_grow(sb, hint);
26}
27
28void strbuf_release(struct strbuf *sb)
29{
30 if (sb->alloc) {
31 free(sb->buf);
32 strbuf_init(sb, 0);
33 }
34}
35
36char *strbuf_detach(struct strbuf *sb, size_t *sz)
37{
38 char *res;
39 strbuf_grow(sb, 0);
40 res = sb->buf;
41 if (sz)
42 *sz = sb->len;
43 strbuf_init(sb, 0);
44 return res;
45}
46
47void strbuf_attach(struct strbuf *sb, void *buf, size_t len, size_t alloc)
48{
49 strbuf_release(sb);
50 sb->buf = buf;
51 sb->len = len;
52 sb->alloc = alloc;
53 strbuf_grow(sb, 0);
54 sb->buf[sb->len] = '\0';
55}
56
57void strbuf_grow(struct strbuf *sb, size_t extra)
58{
59 int new_buf = !sb->alloc;
60 if (unsigned_add_overflows(extra, 1) ||
61 unsigned_add_overflows(sb->len, extra + 1))
62 die("you want to use way too much memory");
63 if (new_buf)
64 sb->buf = NULL;
65 ALLOC_GROW(sb->buf, sb->len + extra + 1, sb->alloc);
66 if (new_buf)
67 sb->buf[0] = '\0';
68}
69
70void strbuf_trim(struct strbuf *sb)
71{
72 char *b = sb->buf;
73 while (sb->len > 0 && isspace((unsigned char)sb->buf[sb->len - 1]))
74 sb->len--;
75 while (sb->len > 0 && isspace(*b)) {
76 b++;
77 sb->len--;
78 }
79 memmove(sb->buf, b, sb->len);
80 sb->buf[sb->len] = '\0';
81}
82void strbuf_rtrim(struct strbuf *sb)
83{
84 while (sb->len > 0 && isspace((unsigned char)sb->buf[sb->len - 1]))
85 sb->len--;
86 sb->buf[sb->len] = '\0';
87}
88
89void strbuf_ltrim(struct strbuf *sb)
90{
91 char *b = sb->buf;
92 while (sb->len > 0 && isspace(*b)) {
93 b++;
94 sb->len--;
95 }
96 memmove(sb->buf, b, sb->len);
97 sb->buf[sb->len] = '\0';
98}
99
100struct strbuf **strbuf_split_buf(const char *str, size_t slen,
101 int terminator, int max)
102{
103 struct strbuf **ret = NULL;
104 size_t nr = 0, alloc = 0;
105 struct strbuf *t;
106
107 while (slen) {
108 int len = slen;
109 if (max <= 0 || nr + 1 < max) {
110 const char *end = memchr(str, terminator, slen);
111 if (end)
112 len = end - str + 1;
113 }
114 t = xmalloc(sizeof(struct strbuf));
115 strbuf_init(t, len);
116 strbuf_add(t, str, len);
117 ALLOC_GROW(ret, nr + 2, alloc);
118 ret[nr++] = t;
119 str += len;
120 slen -= len;
121 }
122 ALLOC_GROW(ret, nr + 1, alloc); /* In case string was empty */
123 ret[nr] = NULL;
124 return ret;
125}
126
127void strbuf_list_free(struct strbuf **sbs)
128{
129 struct strbuf **s = sbs;
130
131 while (*s) {
132 strbuf_release(*s);
133 free(*s++);
134 }
135 free(sbs);
136}
137
138int strbuf_cmp(const struct strbuf *a, const struct strbuf *b)
139{
140 int len = a->len < b->len ? a->len: b->len;
141 int cmp = memcmp(a->buf, b->buf, len);
142 if (cmp)
143 return cmp;
144 return a->len < b->len ? -1: a->len != b->len;
145}
146
147void strbuf_splice(struct strbuf *sb, size_t pos, size_t len,
148 const void *data, size_t dlen)
149{
150 if (unsigned_add_overflows(pos, len))
151 die("you want to use way too much memory");
152 if (pos > sb->len)
153 die("`pos' is too far after the end of the buffer");
154 if (pos + len > sb->len)
155 die("`pos + len' is too far after the end of the buffer");
156
157 if (dlen >= len)
158 strbuf_grow(sb, dlen - len);
159 memmove(sb->buf + pos + dlen,
160 sb->buf + pos + len,
161 sb->len - pos - len);
162 memcpy(sb->buf + pos, data, dlen);
163 strbuf_setlen(sb, sb->len + dlen - len);
164}
165
166void strbuf_insert(struct strbuf *sb, size_t pos, const void *data, size_t len)
167{
168 strbuf_splice(sb, pos, 0, data, len);
169}
170
171void strbuf_remove(struct strbuf *sb, size_t pos, size_t len)
172{
173 strbuf_splice(sb, pos, len, NULL, 0);
174}
175
176void strbuf_add(struct strbuf *sb, const void *data, size_t len)
177{
178 strbuf_grow(sb, len);
179 memcpy(sb->buf + sb->len, data, len);
180 strbuf_setlen(sb, sb->len + len);
181}
182
183void strbuf_adddup(struct strbuf *sb, size_t pos, size_t len)
184{
185 strbuf_grow(sb, len);
186 memcpy(sb->buf + sb->len, sb->buf + pos, len);
187 strbuf_setlen(sb, sb->len + len);
188}
189
190void strbuf_addf(struct strbuf *sb, const char *fmt, ...)
191{
192 va_list ap;
193 va_start(ap, fmt);
194 strbuf_vaddf(sb, fmt, ap);
195 va_end(ap);
196}
197
198static void add_lines(struct strbuf *out,
199 const char *prefix1,
200 const char *prefix2,
201 const char *buf, size_t size)
202{
203 while (size) {
204 const char *prefix;
205 const char *next = memchr(buf, '\n', size);
206 next = next ? (next + 1) : (buf + size);
207
208 prefix = (prefix2 && buf[0] == '\n') ? prefix2 : prefix1;
209 strbuf_addstr(out, prefix);
210 strbuf_add(out, buf, next - buf);
211 size -= next - buf;
212 buf = next;
213 }
214 strbuf_complete_line(out);
215}
216
217void strbuf_add_commented_lines(struct strbuf *out, const char *buf, size_t size)
218{
219 static char prefix1[3];
220 static char prefix2[2];
221
222 if (prefix1[0] != comment_line_char) {
223 sprintf(prefix1, "%c ", comment_line_char);
224 sprintf(prefix2, "%c", comment_line_char);
225 }
226 add_lines(out, prefix1, prefix2, buf, size);
227}
228
229void strbuf_commented_addf(struct strbuf *sb, const char *fmt, ...)
230{
231 va_list params;
232 struct strbuf buf = STRBUF_INIT;
233 int incomplete_line = sb->len && sb->buf[sb->len - 1] != '\n';
234
235 va_start(params, fmt);
236 strbuf_vaddf(&buf, fmt, params);
237 va_end(params);
238
239 strbuf_add_commented_lines(sb, buf.buf, buf.len);
240 if (incomplete_line)
241 sb->buf[--sb->len] = '\0';
242
243 strbuf_release(&buf);
244}
245
246void strbuf_vaddf(struct strbuf *sb, const char *fmt, va_list ap)
247{
248 int len;
249 va_list cp;
250
251 if (!strbuf_avail(sb))
252 strbuf_grow(sb, 64);
253 va_copy(cp, ap);
254 len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, cp);
255 va_end(cp);
256 if (len < 0)
257 die("BUG: your vsnprintf is broken (returned %d)", len);
258 if (len > strbuf_avail(sb)) {
259 strbuf_grow(sb, len);
260 len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap);
261 if (len > strbuf_avail(sb))
262 die("BUG: your vsnprintf is broken (insatiable)");
263 }
264 strbuf_setlen(sb, sb->len + len);
265}
266
267void strbuf_expand(struct strbuf *sb, const char *format, expand_fn_t fn,
268 void *context)
269{
270 for (;;) {
271 const char *percent;
272 size_t consumed;
273
274 percent = strchrnul(format, '%');
275 strbuf_add(sb, format, percent - format);
276 if (!*percent)
277 break;
278 format = percent + 1;
279
280 if (*format == '%') {
281 strbuf_addch(sb, '%');
282 format++;
283 continue;
284 }
285
286 consumed = fn(sb, format, context);
287 if (consumed)
288 format += consumed;
289 else
290 strbuf_addch(sb, '%');
291 }
292}
293
294size_t strbuf_expand_dict_cb(struct strbuf *sb, const char *placeholder,
295 void *context)
296{
297 struct strbuf_expand_dict_entry *e = context;
298 size_t len;
299
300 for (; e->placeholder && (len = strlen(e->placeholder)); e++) {
301 if (!strncmp(placeholder, e->placeholder, len)) {
302 if (e->value)
303 strbuf_addstr(sb, e->value);
304 return len;
305 }
306 }
307 return 0;
308}
309
310void strbuf_addbuf_percentquote(struct strbuf *dst, const struct strbuf *src)
311{
312 int i, len = src->len;
313
314 for (i = 0; i < len; i++) {
315 if (src->buf[i] == '%')
316 strbuf_addch(dst, '%');
317 strbuf_addch(dst, src->buf[i]);
318 }
319}
320
321size_t strbuf_fread(struct strbuf *sb, size_t size, FILE *f)
322{
323 size_t res;
324 size_t oldalloc = sb->alloc;
325
326 strbuf_grow(sb, size);
327 res = fread(sb->buf + sb->len, 1, size, f);
328 if (res > 0)
329 strbuf_setlen(sb, sb->len + res);
330 else if (oldalloc == 0)
331 strbuf_release(sb);
332 return res;
333}
334
335ssize_t strbuf_read(struct strbuf *sb, int fd, size_t hint)
336{
337 size_t oldlen = sb->len;
338 size_t oldalloc = sb->alloc;
339
340 strbuf_grow(sb, hint ? hint : 8192);
341 for (;;) {
342 ssize_t cnt;
343
344 cnt = xread(fd, sb->buf + sb->len, sb->alloc - sb->len - 1);
345 if (cnt < 0) {
346 if (oldalloc == 0)
347 strbuf_release(sb);
348 else
349 strbuf_setlen(sb, oldlen);
350 return -1;
351 }
352 if (!cnt)
353 break;
354 sb->len += cnt;
355 strbuf_grow(sb, 8192);
356 }
357
358 sb->buf[sb->len] = '\0';
359 return sb->len - oldlen;
360}
361
362#define STRBUF_MAXLINK (2*PATH_MAX)
363
364int strbuf_readlink(struct strbuf *sb, const char *path, size_t hint)
365{
366 size_t oldalloc = sb->alloc;
367
368 if (hint < 32)
369 hint = 32;
370
371 while (hint < STRBUF_MAXLINK) {
372 int len;
373
374 strbuf_grow(sb, hint);
375 len = readlink(path, sb->buf, hint);
376 if (len < 0) {
377 if (errno != ERANGE)
378 break;
379 } else if (len < hint) {
380 strbuf_setlen(sb, len);
381 return 0;
382 }
383
384 /* .. the buffer was too small - try again */
385 hint *= 2;
386 }
387 if (oldalloc == 0)
388 strbuf_release(sb);
389 return -1;
390}
391
392int strbuf_getwholeline(struct strbuf *sb, FILE *fp, int term)
393{
394 int ch;
395
396 if (feof(fp))
397 return EOF;
398
399 strbuf_reset(sb);
400 while ((ch = fgetc(fp)) != EOF) {
401 strbuf_grow(sb, 1);
402 sb->buf[sb->len++] = ch;
403 if (ch == term)
404 break;
405 }
406 if (ch == EOF && sb->len == 0)
407 return EOF;
408
409 sb->buf[sb->len] = '\0';
410 return 0;
411}
412
413int strbuf_getline(struct strbuf *sb, FILE *fp, int term)
414{
415 if (strbuf_getwholeline(sb, fp, term))
416 return EOF;
417 if (sb->buf[sb->len-1] == term)
418 strbuf_setlen(sb, sb->len-1);
419 return 0;
420}
421
422int strbuf_getwholeline_fd(struct strbuf *sb, int fd, int term)
423{
424 strbuf_reset(sb);
425
426 while (1) {
427 char ch;
428 ssize_t len = xread(fd, &ch, 1);
429 if (len <= 0)
430 return EOF;
431 strbuf_addch(sb, ch);
432 if (ch == term)
433 break;
434 }
435 return 0;
436}
437
438int strbuf_read_file(struct strbuf *sb, const char *path, size_t hint)
439{
440 int fd, len;
441
442 fd = open(path, O_RDONLY);
443 if (fd < 0)
444 return -1;
445 len = strbuf_read(sb, fd, hint);
446 close(fd);
447 if (len < 0)
448 return -1;
449
450 return len;
451}
452
453void strbuf_add_lines(struct strbuf *out, const char *prefix,
454 const char *buf, size_t size)
455{
456 add_lines(out, prefix, NULL, buf, size);
457}
458
459void strbuf_addstr_xml_quoted(struct strbuf *buf, const char *s)
460{
461 while (*s) {
462 size_t len = strcspn(s, "\"<>&");
463 strbuf_add(buf, s, len);
464 s += len;
465 switch (*s) {
466 case '"':
467 strbuf_addstr(buf, """);
468 break;
469 case '<':
470 strbuf_addstr(buf, "<");
471 break;
472 case '>':
473 strbuf_addstr(buf, ">");
474 break;
475 case '&':
476 strbuf_addstr(buf, "&");
477 break;
478 case 0:
479 return;
480 }
481 s++;
482 }
483}
484
485static int is_rfc3986_reserved(char ch)
486{
487 switch (ch) {
488 case '!': case '*': case '\'': case '(': case ')': case ';':
489 case ':': case '@': case '&': case '=': case '+': case '$':
490 case ',': case '/': case '?': case '#': case '[': case ']':
491 return 1;
492 }
493 return 0;
494}
495
496static int is_rfc3986_unreserved(char ch)
497{
498 return isalnum(ch) ||
499 ch == '-' || ch == '_' || ch == '.' || ch == '~';
500}
501
502static void strbuf_add_urlencode(struct strbuf *sb, const char *s, size_t len,
503 int reserved)
504{
505 strbuf_grow(sb, len);
506 while (len--) {
507 char ch = *s++;
508 if (is_rfc3986_unreserved(ch) ||
509 (!reserved && is_rfc3986_reserved(ch)))
510 strbuf_addch(sb, ch);
511 else
512 strbuf_addf(sb, "%%%02x", ch);
513 }
514}
515
516void strbuf_addstr_urlencode(struct strbuf *sb, const char *s,
517 int reserved)
518{
519 strbuf_add_urlencode(sb, s, strlen(s), reserved);
520}
521
522void strbuf_humanise_bytes(struct strbuf *buf, off_t bytes)
523{
524 if (bytes > 1 << 30) {
525 strbuf_addf(buf, "%u.%2.2u GiB",
526 (int)(bytes >> 30),
527 (int)(bytes & ((1 << 30) - 1)) / 10737419);
528 } else if (bytes > 1 << 20) {
529 int x = bytes + 5243; /* for rounding */
530 strbuf_addf(buf, "%u.%2.2u MiB",
531 x >> 20, ((x & ((1 << 20) - 1)) * 100) >> 20);
532 } else if (bytes > 1 << 10) {
533 int x = bytes + 5; /* for rounding */
534 strbuf_addf(buf, "%u.%2.2u KiB",
535 x >> 10, ((x & ((1 << 10) - 1)) * 100) >> 10);
536 } else {
537 strbuf_addf(buf, "%u bytes", (int)bytes);
538 }
539}
540
541int printf_ln(const char *fmt, ...)
542{
543 int ret;
544 va_list ap;
545 va_start(ap, fmt);
546 ret = vprintf(fmt, ap);
547 va_end(ap);
548 if (ret < 0 || putchar('\n') == EOF)
549 return -1;
550 return ret + 1;
551}
552
553int fprintf_ln(FILE *fp, const char *fmt, ...)
554{
555 int ret;
556 va_list ap;
557 va_start(ap, fmt);
558 ret = vfprintf(fp, fmt, ap);
559 va_end(ap);
560 if (ret < 0 || putc('\n', fp) == EOF)
561 return -1;
562 return ret + 1;
563}