strbuf.con commit Merge branch 'master' into ph/strbuf (39bd2eb)
   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
  53void strbuf_insert(struct strbuf *sb, size_t pos, const void *data, size_t len)
  54{
  55        strbuf_grow(sb, len);
  56        if (pos > sb->len)
  57                die("`pos' is too far after the end of the buffer");
  58        memmove(sb->buf + pos + len, sb->buf + pos, sb->len - pos);
  59        memcpy(sb->buf + pos, data, len);
  60        strbuf_setlen(sb, sb->len + len);
  61}
  62
  63void strbuf_splice(struct strbuf *sb, size_t pos, size_t len,
  64                                   const void *data, size_t dlen)
  65{
  66        if (pos + len < pos)
  67                die("you want to use way too much memory");
  68        if (pos > sb->len)
  69                die("`pos' is too far after the end of the buffer");
  70        if (pos + len > sb->len)
  71                die("`pos + len' is too far after the end of the buffer");
  72
  73        if (dlen >= len)
  74                strbuf_grow(sb, dlen - len);
  75        memmove(sb->buf + pos + dlen,
  76                        sb->buf + pos + len,
  77                        sb->len - pos - len);
  78        memcpy(sb->buf + pos, data, dlen);
  79        strbuf_setlen(sb, sb->len + dlen - len);
  80}
  81
  82void strbuf_add(struct strbuf *sb, const void *data, size_t len)
  83{
  84        strbuf_grow(sb, len);
  85        memcpy(sb->buf + sb->len, data, len);
  86        strbuf_setlen(sb, sb->len + len);
  87}
  88
  89void strbuf_addf(struct strbuf *sb, const char *fmt, ...)
  90{
  91        int len;
  92        va_list ap;
  93
  94        va_start(ap, fmt);
  95        len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap);
  96        va_end(ap);
  97        if (len < 0) {
  98                len = 0;
  99        }
 100        if (len > strbuf_avail(sb)) {
 101                strbuf_grow(sb, len);
 102                va_start(ap, fmt);
 103                len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap);
 104                va_end(ap);
 105                if (len > strbuf_avail(sb)) {
 106                        die("this should not happen, your snprintf is broken");
 107                }
 108        }
 109        strbuf_setlen(sb, sb->len + len);
 110}
 111
 112size_t strbuf_fread(struct strbuf *sb, size_t size, FILE *f)
 113{
 114        size_t res;
 115
 116        strbuf_grow(sb, size);
 117        res = fread(sb->buf + sb->len, 1, size, f);
 118        if (res > 0) {
 119                strbuf_setlen(sb, sb->len + res);
 120        }
 121        return res;
 122}
 123
 124ssize_t strbuf_read(struct strbuf *sb, int fd, size_t hint)
 125{
 126        size_t oldlen = sb->len;
 127
 128        strbuf_grow(sb, hint ? hint : 8192);
 129        for (;;) {
 130                ssize_t cnt;
 131
 132                cnt = xread(fd, sb->buf + sb->len, sb->alloc - sb->len - 1);
 133                if (cnt < 0) {
 134                        strbuf_setlen(sb, oldlen);
 135                        return -1;
 136                }
 137                if (!cnt)
 138                        break;
 139                sb->len += cnt;
 140                strbuf_grow(sb, 8192);
 141        }
 142
 143        sb->buf[sb->len] = '\0';
 144        return sb->len - oldlen;
 145}
 146
 147int strbuf_getline(struct strbuf *sb, FILE *fp, int term)
 148{
 149        int ch;
 150
 151        strbuf_grow(sb, 0);
 152        if (feof(fp))
 153                return EOF;
 154
 155        strbuf_reset(sb);
 156        while ((ch = fgetc(fp)) != EOF) {
 157                if (ch == term)
 158                        break;
 159                strbuf_grow(sb, 1);
 160                sb->buf[sb->len++] = ch;
 161        }
 162        if (ch == EOF && sb->len == 0)
 163                return EOF;
 164
 165        sb->buf[sb->len] = '\0';
 166        return 0;
 167}