strbuf.con commit index-pack: correct --keep[=<msg>] (0e94242)
   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, "&quot;");
 468                        break;
 469                case '<':
 470                        strbuf_addstr(buf, "&lt;");
 471                        break;
 472                case '>':
 473                        strbuf_addstr(buf, "&gt;");
 474                        break;
 475                case '&':
 476                        strbuf_addstr(buf, "&amp;");
 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}