strbuf.con commit Clean up stripspace a bit, use strbuf even more. (6d69b6f)
   1#include "cache.h"
   2
   3void strbuf_init(struct strbuf *sb, size_t hint)
   4{
   5        memset(sb, 0, sizeof(*sb));
   6        if (hint)
   7                strbuf_grow(sb, hint);
   8}
   9
  10void strbuf_release(struct strbuf *sb)
  11{
  12        free(sb->buf);
  13        memset(sb, 0, sizeof(*sb));
  14}
  15
  16void strbuf_reset(struct strbuf *sb)
  17{
  18        if (sb->len)
  19                strbuf_setlen(sb, 0);
  20}
  21
  22char *strbuf_detach(struct strbuf *sb)
  23{
  24        char *res = sb->buf;
  25        strbuf_init(sb, 0);
  26        return res;
  27}
  28
  29void strbuf_attach(struct strbuf *sb, void *buf, size_t len, size_t alloc)
  30{
  31        strbuf_release(sb);
  32        sb->buf   = buf;
  33        sb->len   = len;
  34        sb->alloc = alloc;
  35        strbuf_grow(sb, 0);
  36        sb->buf[sb->len] = '\0';
  37}
  38
  39void strbuf_grow(struct strbuf *sb, size_t extra)
  40{
  41        if (sb->len + extra + 1 <= sb->len)
  42                die("you want to use way too much memory");
  43        ALLOC_GROW(sb->buf, sb->len + extra + 1, sb->alloc);
  44}
  45
  46void strbuf_rtrim(struct strbuf *sb)
  47{
  48        while (sb->len > 0 && isspace((unsigned char)sb->buf[sb->len - 1]))
  49                sb->len--;
  50        sb->buf[sb->len] = '\0';
  51}
  52
  53int strbuf_cmp(struct strbuf *a, struct strbuf *b)
  54{
  55        int cmp;
  56        if (a->len < b->len) {
  57                cmp = memcmp(a->buf, b->buf, a->len);
  58                return cmp ? cmp : -1;
  59        } else {
  60                cmp = memcmp(a->buf, b->buf, b->len);
  61                return cmp ? cmp : a->len != b->len;
  62        }
  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_insert(struct strbuf *sb, size_t pos, const void *data, size_t len)
  85{
  86        strbuf_splice(sb, pos, 0, data, len);
  87}
  88
  89void strbuf_remove(struct strbuf *sb, size_t pos, size_t len)
  90{
  91        strbuf_splice(sb, pos, len, NULL, 0);
  92}
  93
  94void strbuf_add(struct strbuf *sb, const void *data, size_t len)
  95{
  96        strbuf_grow(sb, len);
  97        memcpy(sb->buf + sb->len, data, len);
  98        strbuf_setlen(sb, sb->len + len);
  99}
 100
 101void strbuf_addf(struct strbuf *sb, const char *fmt, ...)
 102{
 103        int len;
 104        va_list ap;
 105
 106        va_start(ap, fmt);
 107        len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap);
 108        va_end(ap);
 109        if (len < 0) {
 110                len = 0;
 111        }
 112        if (len > strbuf_avail(sb)) {
 113                strbuf_grow(sb, len);
 114                va_start(ap, fmt);
 115                len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap);
 116                va_end(ap);
 117                if (len > strbuf_avail(sb)) {
 118                        die("this should not happen, your snprintf is broken");
 119                }
 120        }
 121        strbuf_setlen(sb, sb->len + len);
 122}
 123
 124size_t strbuf_fread(struct strbuf *sb, size_t size, FILE *f)
 125{
 126        size_t res;
 127
 128        strbuf_grow(sb, size);
 129        res = fread(sb->buf + sb->len, 1, size, f);
 130        if (res > 0) {
 131                strbuf_setlen(sb, sb->len + res);
 132        }
 133        return res;
 134}
 135
 136ssize_t strbuf_read(struct strbuf *sb, int fd, size_t hint)
 137{
 138        size_t oldlen = sb->len;
 139
 140        strbuf_grow(sb, hint ? hint : 8192);
 141        for (;;) {
 142                ssize_t cnt;
 143
 144                cnt = xread(fd, sb->buf + sb->len, sb->alloc - sb->len - 1);
 145                if (cnt < 0) {
 146                        strbuf_setlen(sb, oldlen);
 147                        return -1;
 148                }
 149                if (!cnt)
 150                        break;
 151                sb->len += cnt;
 152                strbuf_grow(sb, 8192);
 153        }
 154
 155        sb->buf[sb->len] = '\0';
 156        return sb->len - oldlen;
 157}
 158
 159int strbuf_getline(struct strbuf *sb, FILE *fp, int term)
 160{
 161        int ch;
 162
 163        strbuf_grow(sb, 0);
 164        if (feof(fp))
 165                return EOF;
 166
 167        strbuf_reset(sb);
 168        while ((ch = fgetc(fp)) != EOF) {
 169                if (ch == term)
 170                        break;
 171                strbuf_grow(sb, 1);
 172                sb->buf[sb->len++] = ch;
 173        }
 174        if (ch == EOF && sb->len == 0)
 175                return EOF;
 176
 177        sb->buf[sb->len] = '\0';
 178        return 0;
 179}
 180
 181int strbuf_read_file(struct strbuf *sb, const char *path)
 182{
 183        int fd, len;
 184
 185        fd = open(path, O_RDONLY);
 186        if (fd < 0)
 187                return -1;
 188        len = strbuf_read(sb, fd, 0);
 189        close(fd);
 190        if (len < 0)
 191                return -1;
 192
 193        return len;
 194}