strbuf.c 7.1 KB

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