Code

Strbuf API extensions and fixes.
[git.git] / strbuf.c
1 #include "cache.h"
2 #include "strbuf.h"
4 void strbuf_init(struct strbuf *sb, size_t hint) {
5         memset(sb, 0, sizeof(*sb));
6         if (hint)
7                 strbuf_grow(sb, hint);
8 }
10 void strbuf_release(struct strbuf *sb) {
11         free(sb->buf);
12         memset(sb, 0, sizeof(*sb));
13 }
15 void strbuf_reset(struct strbuf *sb) {
16         if (sb->len)
17                 strbuf_setlen(sb, 0);
18         sb->eof = 0;
19 }
21 char *strbuf_detach(struct strbuf *sb) {
22         char *res = sb->buf;
23         strbuf_init(sb, 0);
24         return res;
25 }
27 void 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 }
33 void 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 }
40 void 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 }
51 void 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 }
57 void strbuf_addf(struct strbuf *sb, const char *fmt, ...) {
58         int len;
59         va_list ap;
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 }
79 size_t strbuf_fread(struct strbuf *sb, size_t size, FILE *f) {
80         size_t res;
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 }
90 ssize_t strbuf_read(struct strbuf *sb, int fd, size_t hint)
91 {
92         size_t oldlen = sb->len;
94         strbuf_grow(sb, hint ? hint : 8192);
95         for (;;) {
96                 ssize_t cnt;
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         }
109         sb->buf[sb->len] = '\0';
110         return sb->len - oldlen;
113 void 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         }
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         }
133         strbuf_grow(sb, 1);
134         sb->buf[sb->len] = '\0';