strbuf.con commit Change semantics of interpolate to work like snprintf. (4acfd1b)
   1#include "cache.h"
   2#include "strbuf.h"
   3
   4void strbuf_init(struct strbuf *sb, size_t hint) {
   5        memset(sb, 0, sizeof(*sb));
   6        if (hint)
   7                strbuf_grow(sb, hint);
   8}
   9
  10void strbuf_release(struct strbuf *sb) {
  11        free(sb->buf);
  12        memset(sb, 0, sizeof(*sb));
  13}
  14
  15void strbuf_reset(struct strbuf *sb) {
  16        if (sb->len)
  17                strbuf_setlen(sb, 0);
  18        sb->eof = 0;
  19}
  20
  21char *strbuf_detach(struct strbuf *sb) {
  22        char *res = sb->buf;
  23        strbuf_init(sb, 0);
  24        return res;
  25}
  26
  27void strbuf_grow(struct strbuf *sb, size_t extra) {
  28        if (sb->len + extra + 1 <= sb->len)
  29                die("you want to use way too much memory");
  30        ALLOC_GROW(sb->buf, sb->len + extra + 1, sb->alloc);
  31}
  32
  33void strbuf_rtrim(struct strbuf *sb)
  34{
  35        while (sb->len > 0 && isspace((unsigned char)sb->buf[sb->len - 1]))
  36                sb->len--;
  37        sb->buf[sb->len] = '\0';
  38}
  39
  40void strbuf_insert(struct strbuf *sb, size_t pos, const void *data, size_t len) {
  41        strbuf_grow(sb, len);
  42        if (pos >= sb->len) {
  43                pos = sb->len;
  44        } else {
  45                memmove(sb->buf + pos + len, sb->buf + pos, sb->len - pos);
  46        }
  47        memcpy(sb->buf + pos, data, len);
  48        strbuf_setlen(sb, sb->len + len);
  49}
  50
  51void strbuf_add(struct strbuf *sb, const void *data, size_t len) {
  52        strbuf_grow(sb, len);
  53        memcpy(sb->buf + sb->len, data, len);
  54        strbuf_setlen(sb, sb->len + len);
  55}
  56
  57void strbuf_addf(struct strbuf *sb, const char *fmt, ...) {
  58        int len;
  59        va_list ap;
  60
  61        va_start(ap, fmt);
  62        len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap);
  63        va_end(ap);
  64        if (len < 0) {
  65                len = 0;
  66        }
  67        if (len > strbuf_avail(sb)) {
  68                strbuf_grow(sb, len);
  69                va_start(ap, fmt);
  70                len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap);
  71                va_end(ap);
  72                if (len > strbuf_avail(sb)) {
  73                        die("this should not happen, your snprintf is broken");
  74                }
  75        }
  76        strbuf_setlen(sb, sb->len + len);
  77}
  78
  79size_t strbuf_fread(struct strbuf *sb, size_t size, FILE *f) {
  80        size_t res;
  81
  82        strbuf_grow(sb, size);
  83        res = fread(sb->buf + sb->len, 1, size, f);
  84        if (res > 0) {
  85                strbuf_setlen(sb, sb->len + res);
  86        }
  87        return res;
  88}
  89
  90ssize_t strbuf_read(struct strbuf *sb, int fd, size_t hint)
  91{
  92        size_t oldlen = sb->len;
  93
  94        strbuf_grow(sb, hint ? hint : 8192);
  95        for (;;) {
  96                ssize_t cnt;
  97
  98                cnt = xread(fd, sb->buf + sb->len, sb->alloc - sb->len - 1);
  99                if (cnt < 0) {
 100                        strbuf_setlen(sb, oldlen);
 101                        return -1;
 102                }
 103                if (!cnt)
 104                        break;
 105                sb->len += cnt;
 106                strbuf_grow(sb, 8192);
 107        }
 108
 109        sb->buf[sb->len] = '\0';
 110        return sb->len - oldlen;
 111}
 112
 113void read_line(struct strbuf *sb, FILE *fp, int term) {
 114        int ch;
 115        if (feof(fp)) {
 116                strbuf_release(sb);
 117                sb->eof = 1;
 118                return;
 119        }
 120
 121        strbuf_reset(sb);
 122        while ((ch = fgetc(fp)) != EOF) {
 123                if (ch == term)
 124                        break;
 125                strbuf_grow(sb, 1);
 126                sb->buf[sb->len++] = ch;
 127        }
 128        if (ch == EOF && sb->len == 0) {
 129                strbuf_release(sb);
 130                sb->eof = 1;
 131        }
 132
 133        strbuf_grow(sb, 1);
 134        sb->buf[sb->len] = '\0';
 135}