]>
Commit | Line | Data |
---|---|---|
812666c8 | 1 | #include "cache.h" |
d1df5743 | 2 | |
917c9a71 PH |
3 | void strbuf_init(struct strbuf *sb, size_t hint) |
4 | { | |
b449f4cf | 5 | memset(sb, 0, sizeof(*sb)); |
f1696ee3 PH |
6 | if (hint) |
7 | strbuf_grow(sb, hint); | |
d1df5743 JH |
8 | } |
9 | ||
917c9a71 PH |
10 | void strbuf_release(struct strbuf *sb) |
11 | { | |
d1df5743 | 12 | free(sb->buf); |
b449f4cf PH |
13 | memset(sb, 0, sizeof(*sb)); |
14 | } | |
15 | ||
917c9a71 PH |
16 | void strbuf_reset(struct strbuf *sb) |
17 | { | |
b449f4cf PH |
18 | if (sb->len) |
19 | strbuf_setlen(sb, 0); | |
b449f4cf PH |
20 | } |
21 | ||
917c9a71 PH |
22 | char *strbuf_detach(struct strbuf *sb) |
23 | { | |
b449f4cf | 24 | char *res = sb->buf; |
f1696ee3 | 25 | strbuf_init(sb, 0); |
b449f4cf PH |
26 | return res; |
27 | } | |
28 | ||
917c9a71 PH |
29 | void 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 | ||
39 | void strbuf_grow(struct strbuf *sb, size_t extra) | |
40 | { | |
b449f4cf PH |
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 | ||
f1696ee3 PH |
46 | void 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 | ||
917c9a71 PH |
53 | void strbuf_insert(struct strbuf *sb, size_t pos, const void *data, size_t len) |
54 | { | |
f1696ee3 | 55 | strbuf_grow(sb, len); |
917c9a71 PH |
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); | |
f1696ee3 PH |
59 | memcpy(sb->buf + pos, data, len); |
60 | strbuf_setlen(sb, sb->len + len); | |
61 | } | |
62 | ||
917c9a71 PH |
63 | void 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 | ||
82 | void strbuf_add(struct strbuf *sb, const void *data, size_t len) | |
83 | { | |
b449f4cf PH |
84 | strbuf_grow(sb, len); |
85 | memcpy(sb->buf + sb->len, data, len); | |
86 | strbuf_setlen(sb, sb->len + len); | |
87 | } | |
88 | ||
917c9a71 PH |
89 | void strbuf_addf(struct strbuf *sb, const char *fmt, ...) |
90 | { | |
b449f4cf PH |
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 | } | |
f1696ee3 | 100 | if (len > strbuf_avail(sb)) { |
b449f4cf PH |
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); | |
f1696ee3 | 105 | if (len > strbuf_avail(sb)) { |
b449f4cf PH |
106 | die("this should not happen, your snprintf is broken"); |
107 | } | |
108 | } | |
109 | strbuf_setlen(sb, sb->len + len); | |
d1df5743 JH |
110 | } |
111 | ||
917c9a71 PH |
112 | size_t strbuf_fread(struct strbuf *sb, size_t size, FILE *f) |
113 | { | |
b449f4cf PH |
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); | |
d1df5743 | 120 | } |
b449f4cf | 121 | return res; |
d1df5743 JH |
122 | } |
123 | ||
f1696ee3 | 124 | ssize_t strbuf_read(struct strbuf *sb, int fd, size_t hint) |
b449f4cf PH |
125 | { |
126 | size_t oldlen = sb->len; | |
127 | ||
f1696ee3 | 128 | strbuf_grow(sb, hint ? hint : 8192); |
b449f4cf PH |
129 | for (;;) { |
130 | ssize_t cnt; | |
131 | ||
b449f4cf PH |
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; | |
f1696ee3 | 140 | strbuf_grow(sb, 8192); |
b449f4cf PH |
141 | } |
142 | ||
143 | sb->buf[sb->len] = '\0'; | |
144 | return sb->len - oldlen; | |
d1df5743 JH |
145 | } |
146 | ||
e6c019d0 | 147 | int strbuf_getline(struct strbuf *sb, FILE *fp, int term) |
917c9a71 | 148 | { |
d1df5743 | 149 | int ch; |
e6c019d0 PH |
150 | |
151 | strbuf_grow(sb, 0); | |
152 | if (feof(fp)) | |
153 | return EOF; | |
b449f4cf PH |
154 | |
155 | strbuf_reset(sb); | |
d1df5743 JH |
156 | while ((ch = fgetc(fp)) != EOF) { |
157 | if (ch == term) | |
158 | break; | |
b449f4cf PH |
159 | strbuf_grow(sb, 1); |
160 | sb->buf[sb->len++] = ch; | |
d1df5743 | 161 | } |
e6c019d0 PH |
162 | if (ch == EOF && sb->len == 0) |
163 | return EOF; | |
b449f4cf | 164 | |
b449f4cf | 165 | sb->buf[sb->len] = '\0'; |
e6c019d0 | 166 | return 0; |
d1df5743 | 167 | } |