1 #include "cache.h" 2 3 int 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 */ 17 char strbuf_slopbuf[1]; 18 19 void 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 27 void strbuf_release(struct strbuf *sb) 28 { 29 if (sb->alloc) { 30 free(sb->buf); 31 strbuf_init(sb, 0); 32 } 33 } 34 35 char *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 44 void strbuf_grow(struct strbuf *sb, size_t extra) 45 { 46 if (sb->len + extra + 1 <= sb->len) 47 die("you want to use way too much memory"); 48 if (!sb->alloc) 49 sb->buf = NULL; 50 ALLOC_GROW(sb->buf, sb->len + extra + 1, sb->alloc); 51 } 52 53 static void strbuf_splice(struct strbuf *sb, size_t pos, size_t len, 54 const void *data, size_t dlen) 55 { 56 if (pos + len < pos) 57 die("you want to use way too much memory"); 58 if (pos > sb->len) 59 die("`pos' is too far after the end of the buffer"); 60 if (pos + len > sb->len) 61 die("`pos + len' is too far after the end of the buffer"); 62 63 if (dlen >= len) 64 strbuf_grow(sb, dlen - len); 65 memmove(sb->buf + pos + dlen, 66 sb->buf + pos + len, 67 sb->len - pos - len); 68 memcpy(sb->buf + pos, data, dlen); 69 strbuf_setlen(sb, sb->len + dlen - len); 70 } 71 72 void strbuf_remove(struct strbuf *sb, size_t pos, size_t len) 73 { 74 strbuf_splice(sb, pos, len, NULL, 0); 75 } 76 77 void strbuf_add(struct strbuf *sb, const void *data, size_t len) 78 { 79 strbuf_grow(sb, len); 80 memcpy(sb->buf + sb->len, data, len); 81 strbuf_setlen(sb, sb->len + len); 82 } 83 84 void strbuf_addf(struct strbuf *sb, const char *fmt, ...) 85 { 86 int len; 87 va_list ap; 88 89 if (!strbuf_avail(sb)) 90 strbuf_grow(sb, 64); 91 va_start(ap, fmt); 92 len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap); 93 va_end(ap); 94 if (len < 0) 95 die("your vsnprintf is broken"); 96 if (len > strbuf_avail(sb)) { 97 strbuf_grow(sb, len); 98 va_start(ap, fmt); 99 len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap); 100 va_end(ap); 101 if (len > strbuf_avail(sb)) { 102 die("this should not happen, your snprintf is broken"); 103 } 104 } 105 strbuf_setlen(sb, sb->len + len); 106 } 107 108 ssize_t strbuf_read(struct strbuf *sb, int fd, ssize_t hint) 109 { 110 size_t oldlen = sb->len; 111 size_t oldalloc = sb->alloc; 112 113 strbuf_grow(sb, hint ? hint : 8192); 114 for (;;) { 115 ssize_t cnt; 116 117 cnt = read(fd, sb->buf + sb->len, sb->alloc - sb->len - 1); 118 if (cnt < 0) { 119 if (oldalloc == 0) 120 strbuf_release(sb); 121 else 122 strbuf_setlen(sb, oldlen); 123 return -1; 124 } 125 if (!cnt) 126 break; 127 sb->len += cnt; 128 strbuf_grow(sb, 8192); 129 } 130 131 sb->buf[sb->len] = '\0'; 132 return sb->len - oldlen; 133 } 134