Strbuf API extensions and fixes.
[git] / strbuf.c
1 #include "cache.h"
2 #include "strbuf.h"
3
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 }
9
10 void strbuf_release(struct strbuf *sb) {
11         free(sb->buf);
12         memset(sb, 0, sizeof(*sb));
13 }
14
15 void strbuf_reset(struct strbuf *sb) {
16         if (sb->len)
17                 strbuf_setlen(sb, 0);
18         sb->eof = 0;
19 }
20
21 char *strbuf_detach(struct strbuf *sb) {
22         char *res = sb->buf;
23         strbuf_init(sb, 0);
24         return res;
25 }
26
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 }
32
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 }
39
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 }
50
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 }
56
57 void 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
79 size_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
90 ssize_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
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         }
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 }