at v2.6.32 7.3 kB view raw
1#include "cache.h" 2 3int prefixcmp(const char *str, const char *prefix) 4{ 5 for (; ; str++, prefix++) 6 if (!*prefix) 7 return 0; 8 else if (*str != *prefix) 9 return (unsigned char)*prefix - (unsigned char)*str; 10} 11 12/* 13 * Used as the default ->buf value, so that people can always assume 14 * buf is non NULL and ->buf is NUL terminated even for a freshly 15 * initialized strbuf. 16 */ 17char strbuf_slopbuf[1]; 18 19void strbuf_init(struct strbuf *sb, ssize_t hint) 20{ 21 sb->alloc = sb->len = 0; 22 sb->buf = strbuf_slopbuf; 23 if (hint) 24 strbuf_grow(sb, hint); 25} 26 27void strbuf_release(struct strbuf *sb) 28{ 29 if (sb->alloc) { 30 free(sb->buf); 31 strbuf_init(sb, 0); 32 } 33} 34 35char *strbuf_detach(struct strbuf *sb, size_t *sz) 36{ 37 char *res = sb->alloc ? sb->buf : NULL; 38 if (sz) 39 *sz = sb->len; 40 strbuf_init(sb, 0); 41 return res; 42} 43 44void strbuf_attach(struct strbuf *sb, void *buf, size_t len, size_t alloc) 45{ 46 strbuf_release(sb); 47 sb->buf = buf; 48 sb->len = len; 49 sb->alloc = alloc; 50 strbuf_grow(sb, 0); 51 sb->buf[sb->len] = '\0'; 52} 53 54void strbuf_grow(struct strbuf *sb, size_t extra) 55{ 56 if (sb->len + extra + 1 <= sb->len) 57 die("you want to use way too much memory"); 58 if (!sb->alloc) 59 sb->buf = NULL; 60 ALLOC_GROW(sb->buf, sb->len + extra + 1, sb->alloc); 61} 62 63void strbuf_trim(struct strbuf *sb) 64{ 65 char *b = sb->buf; 66 while (sb->len > 0 && isspace((unsigned char)sb->buf[sb->len - 1])) 67 sb->len--; 68 while (sb->len > 0 && isspace(*b)) { 69 b++; 70 sb->len--; 71 } 72 memmove(sb->buf, b, sb->len); 73 sb->buf[sb->len] = '\0'; 74} 75void strbuf_rtrim(struct strbuf *sb) 76{ 77 while (sb->len > 0 && isspace((unsigned char)sb->buf[sb->len - 1])) 78 sb->len--; 79 sb->buf[sb->len] = '\0'; 80} 81 82void strbuf_ltrim(struct strbuf *sb) 83{ 84 char *b = sb->buf; 85 while (sb->len > 0 && isspace(*b)) { 86 b++; 87 sb->len--; 88 } 89 memmove(sb->buf, b, sb->len); 90 sb->buf[sb->len] = '\0'; 91} 92 93void strbuf_tolower(struct strbuf *sb) 94{ 95 unsigned int i; 96 97 for (i = 0; i < sb->len; i++) 98 sb->buf[i] = tolower(sb->buf[i]); 99} 100 101struct strbuf **strbuf_split(const struct strbuf *sb, int delim) 102{ 103 int alloc = 2, pos = 0; 104 char *n, *p; 105 struct strbuf **ret; 106 struct strbuf *t; 107 108 ret = calloc(alloc, sizeof(struct strbuf *)); 109 p = n = sb->buf; 110 while (n < sb->buf + sb->len) { 111 int len; 112 n = memchr(n, delim, sb->len - (n - sb->buf)); 113 if (pos + 1 >= alloc) { 114 alloc = alloc * 2; 115 ret = realloc(ret, sizeof(struct strbuf *) * alloc); 116 } 117 if (!n) 118 n = sb->buf + sb->len - 1; 119 len = n - p + 1; 120 t = malloc(sizeof(struct strbuf)); 121 strbuf_init(t, len); 122 strbuf_add(t, p, len); 123 ret[pos] = t; 124 ret[++pos] = NULL; 125 p = ++n; 126 } 127 return ret; 128} 129 130void strbuf_list_free(struct strbuf **sbs) 131{ 132 struct strbuf **s = sbs; 133 134 while (*s) { 135 strbuf_release(*s); 136 free(*s++); 137 } 138 free(sbs); 139} 140 141int strbuf_cmp(const struct strbuf *a, const struct strbuf *b) 142{ 143 int len = a->len < b->len ? a->len: b->len; 144 int cmp = memcmp(a->buf, b->buf, len); 145 if (cmp) 146 return cmp; 147 return a->len < b->len ? -1: a->len != b->len; 148} 149 150void strbuf_splice(struct strbuf *sb, size_t pos, size_t len, 151 const void *data, size_t dlen) 152{ 153 if (pos + len < pos) 154 die("you want to use way too much memory"); 155 if (pos > sb->len) 156 die("`pos' is too far after the end of the buffer"); 157 if (pos + len > sb->len) 158 die("`pos + len' is too far after the end of the buffer"); 159 160 if (dlen >= len) 161 strbuf_grow(sb, dlen - len); 162 memmove(sb->buf + pos + dlen, 163 sb->buf + pos + len, 164 sb->len - pos - len); 165 memcpy(sb->buf + pos, data, dlen); 166 strbuf_setlen(sb, sb->len + dlen - len); 167} 168 169void strbuf_insert(struct strbuf *sb, size_t pos, const void *data, size_t len) 170{ 171 strbuf_splice(sb, pos, 0, data, len); 172} 173 174void strbuf_remove(struct strbuf *sb, size_t pos, size_t len) 175{ 176 strbuf_splice(sb, pos, len, NULL, 0); 177} 178 179void strbuf_add(struct strbuf *sb, const void *data, size_t len) 180{ 181 strbuf_grow(sb, len); 182 memcpy(sb->buf + sb->len, data, len); 183 strbuf_setlen(sb, sb->len + len); 184} 185 186void strbuf_adddup(struct strbuf *sb, size_t pos, size_t len) 187{ 188 strbuf_grow(sb, len); 189 memcpy(sb->buf + sb->len, sb->buf + pos, len); 190 strbuf_setlen(sb, sb->len + len); 191} 192 193void strbuf_addf(struct strbuf *sb, const char *fmt, ...) 194{ 195 int len; 196 va_list ap; 197 198 if (!strbuf_avail(sb)) 199 strbuf_grow(sb, 64); 200 va_start(ap, fmt); 201 len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap); 202 va_end(ap); 203 if (len < 0) 204 die("your vsnprintf is broken"); 205 if (len > strbuf_avail(sb)) { 206 strbuf_grow(sb, len); 207 va_start(ap, fmt); 208 len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap); 209 va_end(ap); 210 if (len > strbuf_avail(sb)) { 211 die("this should not happen, your snprintf is broken"); 212 } 213 } 214 strbuf_setlen(sb, sb->len + len); 215} 216 217void strbuf_expand(struct strbuf *sb, const char *format, expand_fn_t fn, 218 void *context) 219{ 220 for (;;) { 221 const char *percent; 222 size_t consumed; 223 224 percent = strchrnul(format, '%'); 225 strbuf_add(sb, format, percent - format); 226 if (!*percent) 227 break; 228 format = percent + 1; 229 230 consumed = fn(sb, format, context); 231 if (consumed) 232 format += consumed; 233 else 234 strbuf_addch(sb, '%'); 235 } 236} 237 238size_t strbuf_expand_dict_cb(struct strbuf *sb, const char *placeholder, 239 void *context) 240{ 241 struct strbuf_expand_dict_entry *e = context; 242 size_t len; 243 244 for (; e->placeholder && (len = strlen(e->placeholder)); e++) { 245 if (!strncmp(placeholder, e->placeholder, len)) { 246 if (e->value) 247 strbuf_addstr(sb, e->value); 248 return len; 249 } 250 } 251 return 0; 252} 253 254size_t strbuf_fread(struct strbuf *sb, size_t size, FILE *f) 255{ 256 size_t res; 257 size_t oldalloc = sb->alloc; 258 259 strbuf_grow(sb, size); 260 res = fread(sb->buf + sb->len, 1, size, f); 261 if (res > 0) 262 strbuf_setlen(sb, sb->len + res); 263 else if (oldalloc == 0) 264 strbuf_release(sb); 265 return res; 266} 267 268ssize_t strbuf_read(struct strbuf *sb, int fd, ssize_t hint) 269{ 270 size_t oldlen = sb->len; 271 size_t oldalloc = sb->alloc; 272 273 strbuf_grow(sb, hint ? hint : 8192); 274 for (;;) { 275 ssize_t cnt; 276 277 cnt = read(fd, sb->buf + sb->len, sb->alloc - sb->len - 1); 278 if (cnt < 0) { 279 if (oldalloc == 0) 280 strbuf_release(sb); 281 else 282 strbuf_setlen(sb, oldlen); 283 return -1; 284 } 285 if (!cnt) 286 break; 287 sb->len += cnt; 288 strbuf_grow(sb, 8192); 289 } 290 291 sb->buf[sb->len] = '\0'; 292 return sb->len - oldlen; 293} 294 295#define STRBUF_MAXLINK (2*PATH_MAX) 296 297int strbuf_readlink(struct strbuf *sb, const char *path, ssize_t hint) 298{ 299 size_t oldalloc = sb->alloc; 300 301 if (hint < 32) 302 hint = 32; 303 304 while (hint < STRBUF_MAXLINK) { 305 ssize_t len; 306 307 strbuf_grow(sb, hint); 308 len = readlink(path, sb->buf, hint); 309 if (len < 0) { 310 if (errno != ERANGE) 311 break; 312 } else if (len < hint) { 313 strbuf_setlen(sb, len); 314 return 0; 315 } 316 317 /* .. the buffer was too small - try again */ 318 hint *= 2; 319 } 320 if (oldalloc == 0) 321 strbuf_release(sb); 322 return -1; 323} 324 325int strbuf_getline(struct strbuf *sb, FILE *fp, int term) 326{ 327 int ch; 328 329 strbuf_grow(sb, 0); 330 if (feof(fp)) 331 return EOF; 332 333 strbuf_reset(sb); 334 while ((ch = fgetc(fp)) != EOF) { 335 if (ch == term) 336 break; 337 strbuf_grow(sb, 1); 338 sb->buf[sb->len++] = ch; 339 } 340 if (ch == EOF && sb->len == 0) 341 return EOF; 342 343 sb->buf[sb->len] = '\0'; 344 return 0; 345} 346 347int strbuf_read_file(struct strbuf *sb, const char *path, ssize_t hint) 348{ 349 int fd, len; 350 351 fd = open(path, O_RDONLY); 352 if (fd < 0) 353 return -1; 354 len = strbuf_read(sb, fd, hint); 355 close(fd); 356 if (len < 0) 357 return -1; 358 359 return len; 360}