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