4 int starts_with(const char *str, const char *prefix)
6 for (; ; str++, prefix++)
9 else if (*str != *prefix)
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
18 char strbuf_slopbuf[1];
20 void strbuf_init(struct strbuf *sb, size_t hint)
22 sb->alloc = sb->len = 0;
23 sb->buf = strbuf_slopbuf;
25 strbuf_grow(sb, hint);
28 void strbuf_release(struct strbuf *sb)
36 char *strbuf_detach(struct strbuf *sb, size_t *sz)
47 void strbuf_attach(struct strbuf *sb, void *buf, size_t len, size_t alloc)
54 sb->buf[sb->len] = '\0';
57 void strbuf_grow(struct strbuf *sb, size_t extra)
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");
65 ALLOC_GROW(sb->buf, sb->len + extra + 1, sb->alloc);
70 void strbuf_trim(struct strbuf *sb)
73 while (sb->len > 0 && isspace((unsigned char)sb->buf[sb->len - 1]))
75 while (sb->len > 0 && isspace(*b)) {
79 memmove(sb->buf, b, sb->len);
80 sb->buf[sb->len] = '\0';
82 void strbuf_rtrim(struct strbuf *sb)
84 while (sb->len > 0 && isspace((unsigned char)sb->buf[sb->len - 1]))
86 sb->buf[sb->len] = '\0';
89 void strbuf_ltrim(struct strbuf *sb)
92 while (sb->len > 0 && isspace(*b)) {
96 memmove(sb->buf, b, sb->len);
97 sb->buf[sb->len] = '\0';
100 struct strbuf **strbuf_split_buf(const char *str, size_t slen,
101 int terminator, int max)
103 struct strbuf **ret = NULL;
104 size_t nr = 0, alloc = 0;
109 if (max <= 0 || nr + 1 < max) {
110 const char *end = memchr(str, terminator, slen);
114 t = xmalloc(sizeof(struct strbuf));
116 strbuf_add(t, str, len);
117 ALLOC_GROW(ret, nr + 2, alloc);
122 ALLOC_GROW(ret, nr + 1, alloc); /* In case string was empty */
127 void strbuf_list_free(struct strbuf **sbs)
129 struct strbuf **s = sbs;
138 int strbuf_cmp(const struct strbuf *a, const struct strbuf *b)
140 int len = a->len < b->len ? a->len: b->len;
141 int cmp = memcmp(a->buf, b->buf, len);
144 return a->len < b->len ? -1: a->len != b->len;
147 void strbuf_splice(struct strbuf *sb, size_t pos, size_t len,
148 const void *data, size_t dlen)
150 if (unsigned_add_overflows(pos, len))
151 die("you want to use way too much memory");
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");
158 strbuf_grow(sb, dlen - len);
159 memmove(sb->buf + pos + dlen,
161 sb->len - pos - len);
162 memcpy(sb->buf + pos, data, dlen);
163 strbuf_setlen(sb, sb->len + dlen - len);
166 void strbuf_insert(struct strbuf *sb, size_t pos, const void *data, size_t len)
168 strbuf_splice(sb, pos, 0, data, len);
171 void strbuf_remove(struct strbuf *sb, size_t pos, size_t len)
173 strbuf_splice(sb, pos, len, NULL, 0);
176 void strbuf_add(struct strbuf *sb, const void *data, size_t len)
178 strbuf_grow(sb, len);
179 memcpy(sb->buf + sb->len, data, len);
180 strbuf_setlen(sb, sb->len + len);
183 void strbuf_adddup(struct strbuf *sb, size_t pos, size_t len)
185 strbuf_grow(sb, len);
186 memcpy(sb->buf + sb->len, sb->buf + pos, len);
187 strbuf_setlen(sb, sb->len + len);
190 void strbuf_addf(struct strbuf *sb, const char *fmt, ...)
194 strbuf_vaddf(sb, fmt, ap);
198 static void add_lines(struct strbuf *out,
201 const char *buf, size_t size)
205 const char *next = memchr(buf, '\n', size);
206 next = next ? (next + 1) : (buf + size);
208 prefix = (prefix2 && buf[0] == '\n') ? prefix2 : prefix1;
209 strbuf_addstr(out, prefix);
210 strbuf_add(out, buf, next - buf);
214 strbuf_complete_line(out);
217 void strbuf_add_commented_lines(struct strbuf *out, const char *buf, size_t size)
219 static char prefix1[3];
220 static char prefix2[2];
222 if (prefix1[0] != comment_line_char) {
223 sprintf(prefix1, "%c ", comment_line_char);
224 sprintf(prefix2, "%c", comment_line_char);
226 add_lines(out, prefix1, prefix2, buf, size);
229 void strbuf_commented_addf(struct strbuf *sb, const char *fmt, ...)
232 struct strbuf buf = STRBUF_INIT;
233 int incomplete_line = sb->len && sb->buf[sb->len - 1] != '\n';
235 va_start(params, fmt);
236 strbuf_vaddf(&buf, fmt, params);
239 strbuf_add_commented_lines(sb, buf.buf, buf.len);
241 sb->buf[--sb->len] = '\0';
243 strbuf_release(&buf);
246 void strbuf_vaddf(struct strbuf *sb, const char *fmt, va_list ap)
251 if (!strbuf_avail(sb))
254 len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, cp);
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)");
264 strbuf_setlen(sb, sb->len + len);
267 void strbuf_expand(struct strbuf *sb, const char *format, expand_fn_t fn,
274 percent = strchrnul(format, '%');
275 strbuf_add(sb, format, percent - format);
278 format = percent + 1;
280 if (*format == '%') {
281 strbuf_addch(sb, '%');
286 consumed = fn(sb, format, context);
290 strbuf_addch(sb, '%');
294 size_t strbuf_expand_dict_cb(struct strbuf *sb, const char *placeholder,
297 struct strbuf_expand_dict_entry *e = context;
300 for (; e->placeholder && (len = strlen(e->placeholder)); e++) {
301 if (!strncmp(placeholder, e->placeholder, len)) {
303 strbuf_addstr(sb, e->value);
310 void strbuf_addbuf_percentquote(struct strbuf *dst, const struct strbuf *src)
312 int i, len = src->len;
314 for (i = 0; i < len; i++) {
315 if (src->buf[i] == '%')
316 strbuf_addch(dst, '%');
317 strbuf_addch(dst, src->buf[i]);
321 size_t strbuf_fread(struct strbuf *sb, size_t size, FILE *f)
324 size_t oldalloc = sb->alloc;
326 strbuf_grow(sb, size);
327 res = fread(sb->buf + sb->len, 1, size, f);
329 strbuf_setlen(sb, sb->len + res);
330 else if (oldalloc == 0)
335 ssize_t strbuf_read(struct strbuf *sb, int fd, size_t hint)
337 size_t oldlen = sb->len;
338 size_t oldalloc = sb->alloc;
340 strbuf_grow(sb, hint ? hint : 8192);
344 cnt = xread(fd, sb->buf + sb->len, sb->alloc - sb->len - 1);
349 strbuf_setlen(sb, oldlen);
355 strbuf_grow(sb, 8192);
358 sb->buf[sb->len] = '\0';
359 return sb->len - oldlen;
362 #define STRBUF_MAXLINK (2*PATH_MAX)
364 int strbuf_readlink(struct strbuf *sb, const char *path, size_t hint)
366 size_t oldalloc = sb->alloc;
371 while (hint < STRBUF_MAXLINK) {
374 strbuf_grow(sb, hint);
375 len = readlink(path, sb->buf, hint);
379 } else if (len < hint) {
380 strbuf_setlen(sb, len);
384 /* .. the buffer was too small - try again */
392 int strbuf_getwholeline(struct strbuf *sb, FILE *fp, int term)
400 while ((ch = fgetc(fp)) != EOF) {
402 sb->buf[sb->len++] = ch;
406 if (ch == EOF && sb->len == 0)
409 sb->buf[sb->len] = '\0';
413 int strbuf_getline(struct strbuf *sb, FILE *fp, int term)
415 if (strbuf_getwholeline(sb, fp, term))
417 if (sb->buf[sb->len-1] == term)
418 strbuf_setlen(sb, sb->len-1);
422 int strbuf_getwholeline_fd(struct strbuf *sb, int fd, int term)
428 ssize_t len = xread(fd, &ch, 1);
431 strbuf_addch(sb, ch);
438 int strbuf_read_file(struct strbuf *sb, const char *path, size_t hint)
442 fd = open(path, O_RDONLY);
445 len = strbuf_read(sb, fd, hint);
453 void strbuf_add_lines(struct strbuf *out, const char *prefix,
454 const char *buf, size_t size)
456 add_lines(out, prefix, NULL, buf, size);
459 void strbuf_addstr_xml_quoted(struct strbuf *buf, const char *s)
462 size_t len = strcspn(s, "\"<>&");
463 strbuf_add(buf, s, len);
467 strbuf_addstr(buf, """);
470 strbuf_addstr(buf, "<");
473 strbuf_addstr(buf, ">");
476 strbuf_addstr(buf, "&");
485 static int is_rfc3986_reserved(char ch)
488 case '!': case '*': case '\'': case '(': case ')': case ';':
489 case ':': case '@': case '&': case '=': case '+': case '$':
490 case ',': case '/': case '?': case '#': case '[': case ']':
496 static int is_rfc3986_unreserved(char ch)
498 return isalnum(ch) ||
499 ch == '-' || ch == '_' || ch == '.' || ch == '~';
502 static void strbuf_add_urlencode(struct strbuf *sb, const char *s, size_t len,
505 strbuf_grow(sb, len);
508 if (is_rfc3986_unreserved(ch) ||
509 (!reserved && is_rfc3986_reserved(ch)))
510 strbuf_addch(sb, ch);
512 strbuf_addf(sb, "%%%02x", ch);
516 void strbuf_addstr_urlencode(struct strbuf *sb, const char *s,
519 strbuf_add_urlencode(sb, s, strlen(s), reserved);
522 void strbuf_humanise_bytes(struct strbuf *buf, off_t bytes)
524 if (bytes > 1 << 30) {
525 strbuf_addf(buf, "%u.%2.2u GiB",
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);
537 strbuf_addf(buf, "%u bytes", (int)bytes);
541 int printf_ln(const char *fmt, ...)
546 ret = vprintf(fmt, ap);
548 if (ret < 0 || putchar('\n') == EOF)
553 int fprintf_ln(FILE *fp, const char *fmt, ...)
558 ret = vfprintf(fp, fmt, ap);
560 if (ret < 0 || putc('\n', fp) == EOF)