X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=strbuf.c;h=cbada946c4e73a403cb2d237f8aebfcda5c88ac4;hb=4d1012c3709e356107d0fb0e3bf5a39e0d5c209d;hp=c5f9e2a28f1441e0ae79e3cac3a3640bf943ed52;hpb=ba3ed09728cb25e004d3b732de14fca8aeb602f6;p=git.git diff --git a/strbuf.c b/strbuf.c index c5f9e2a28..cbada946c 100644 --- a/strbuf.c +++ b/strbuf.c @@ -1,28 +1,33 @@ #include "cache.h" +/* + * Used as the default ->buf value, so that people can always assume + * buf is non NULL and ->buf is NUL terminated even for a freshly + * initialized strbuf. + */ +char strbuf_slopbuf[1]; + void strbuf_init(struct strbuf *sb, size_t hint) { - memset(sb, 0, sizeof(*sb)); + sb->alloc = sb->len = 0; + sb->buf = strbuf_slopbuf; if (hint) strbuf_grow(sb, hint); } void strbuf_release(struct strbuf *sb) { - free(sb->buf); - memset(sb, 0, sizeof(*sb)); -} - -void strbuf_reset(struct strbuf *sb) -{ - if (sb->len) - strbuf_setlen(sb, 0); - sb->eof = 0; + if (sb->alloc) { + free(sb->buf); + strbuf_init(sb, 0); + } } -char *strbuf_detach(struct strbuf *sb) +char *strbuf_detach(struct strbuf *sb, size_t *sz) { - char *res = sb->buf; + char *res = sb->alloc ? sb->buf : NULL; + if (sz) + *sz = sb->len; strbuf_init(sb, 0); return res; } @@ -41,6 +46,8 @@ void strbuf_grow(struct strbuf *sb, size_t extra) { if (sb->len + extra + 1 <= sb->len) die("you want to use way too much memory"); + if (!sb->alloc) + sb->buf = NULL; ALLOC_GROW(sb->buf, sb->len + extra + 1, sb->alloc); } @@ -51,14 +58,16 @@ void strbuf_rtrim(struct strbuf *sb) sb->buf[sb->len] = '\0'; } -void strbuf_insert(struct strbuf *sb, size_t pos, const void *data, size_t len) +int strbuf_cmp(struct strbuf *a, struct strbuf *b) { - strbuf_grow(sb, len); - if (pos > sb->len) - die("`pos' is too far after the end of the buffer"); - memmove(sb->buf + pos + len, sb->buf + pos, sb->len - pos); - memcpy(sb->buf + pos, data, len); - strbuf_setlen(sb, sb->len + len); + int cmp; + if (a->len < b->len) { + cmp = memcmp(a->buf, b->buf, a->len); + return cmp ? cmp : -1; + } else { + cmp = memcmp(a->buf, b->buf, b->len); + return cmp ? cmp : a->len != b->len; + } } void strbuf_splice(struct strbuf *sb, size_t pos, size_t len, @@ -80,6 +89,16 @@ void strbuf_splice(struct strbuf *sb, size_t pos, size_t len, strbuf_setlen(sb, sb->len + dlen - len); } +void strbuf_insert(struct strbuf *sb, size_t pos, const void *data, size_t len) +{ + strbuf_splice(sb, pos, 0, data, len); +} + +void strbuf_remove(struct strbuf *sb, size_t pos, size_t len) +{ + strbuf_splice(sb, pos, len, NULL, 0); +} + void strbuf_add(struct strbuf *sb, const void *data, size_t len) { strbuf_grow(sb, len); @@ -92,12 +111,13 @@ void strbuf_addf(struct strbuf *sb, const char *fmt, ...) int len; va_list ap; + if (!strbuf_avail(sb)) + strbuf_grow(sb, 64); va_start(ap, fmt); len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap); va_end(ap); - if (len < 0) { - len = 0; - } + if (len < 0) + die("your vsnprintf is broken"); if (len > strbuf_avail(sb)) { strbuf_grow(sb, len); va_start(ap, fmt); @@ -145,14 +165,13 @@ ssize_t strbuf_read(struct strbuf *sb, int fd, size_t hint) return sb->len - oldlen; } -void read_line(struct strbuf *sb, FILE *fp, int term) +int strbuf_getline(struct strbuf *sb, FILE *fp, int term) { int ch; - if (feof(fp)) { - strbuf_release(sb); - sb->eof = 1; - return; - } + + strbuf_grow(sb, 0); + if (feof(fp)) + return EOF; strbuf_reset(sb); while ((ch = fgetc(fp)) != EOF) { @@ -161,11 +180,24 @@ void read_line(struct strbuf *sb, FILE *fp, int term) strbuf_grow(sb, 1); sb->buf[sb->len++] = ch; } - if (ch == EOF && sb->len == 0) { - strbuf_release(sb); - sb->eof = 1; - } + if (ch == EOF && sb->len == 0) + return EOF; - strbuf_grow(sb, 1); sb->buf[sb->len] = '\0'; + return 0; +} + +int strbuf_read_file(struct strbuf *sb, const char *path, size_t hint) +{ + int fd, len; + + fd = open(path, O_RDONLY); + if (fd < 0) + return -1; + len = strbuf_read(sb, fd, hint); + close(fd); + if (len < 0) + return -1; + + return len; }