PageRenderTime 68ms CodeModel.GetById 33ms RepoModel.GetById 1ms app.codeStats 0ms

/strbuf.c

https://gitlab.com/Blueprint-Marketing/git
C | 820 lines | 724 code | 77 blank | 19 comment | 107 complexity | f2942f93640cacc4c2571c89b98e0bb2 MD5 | raw file
  1. #include "cache.h"
  2. #include "refs.h"
  3. #include "utf8.h"
  4. int starts_with(const char *str, const char *prefix)
  5. {
  6. for (; ; str++, prefix++)
  7. if (!*prefix)
  8. return 1;
  9. else if (*str != *prefix)
  10. return 0;
  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. void strbuf_init(struct strbuf *sb, size_t hint)
  19. {
  20. sb->alloc = sb->len = 0;
  21. sb->buf = strbuf_slopbuf;
  22. if (hint)
  23. strbuf_grow(sb, hint);
  24. }
  25. void strbuf_release(struct strbuf *sb)
  26. {
  27. if (sb->alloc) {
  28. free(sb->buf);
  29. strbuf_init(sb, 0);
  30. }
  31. }
  32. char *strbuf_detach(struct strbuf *sb, size_t *sz)
  33. {
  34. char *res;
  35. strbuf_grow(sb, 0);
  36. res = sb->buf;
  37. if (sz)
  38. *sz = sb->len;
  39. strbuf_init(sb, 0);
  40. return res;
  41. }
  42. void strbuf_attach(struct strbuf *sb, void *buf, size_t len, size_t alloc)
  43. {
  44. strbuf_release(sb);
  45. sb->buf = buf;
  46. sb->len = len;
  47. sb->alloc = alloc;
  48. strbuf_grow(sb, 0);
  49. sb->buf[sb->len] = '\0';
  50. }
  51. void strbuf_grow(struct strbuf *sb, size_t extra)
  52. {
  53. int new_buf = !sb->alloc;
  54. if (unsigned_add_overflows(extra, 1) ||
  55. unsigned_add_overflows(sb->len, extra + 1))
  56. die("you want to use way too much memory");
  57. if (new_buf)
  58. sb->buf = NULL;
  59. ALLOC_GROW(sb->buf, sb->len + extra + 1, sb->alloc);
  60. if (new_buf)
  61. sb->buf[0] = '\0';
  62. }
  63. void strbuf_trim(struct strbuf *sb)
  64. {
  65. strbuf_rtrim(sb);
  66. strbuf_ltrim(sb);
  67. }
  68. void strbuf_rtrim(struct strbuf *sb)
  69. {
  70. while (sb->len > 0 && isspace((unsigned char)sb->buf[sb->len - 1]))
  71. sb->len--;
  72. sb->buf[sb->len] = '\0';
  73. }
  74. void strbuf_ltrim(struct strbuf *sb)
  75. {
  76. char *b = sb->buf;
  77. while (sb->len > 0 && isspace(*b)) {
  78. b++;
  79. sb->len--;
  80. }
  81. memmove(sb->buf, b, sb->len);
  82. sb->buf[sb->len] = '\0';
  83. }
  84. int strbuf_reencode(struct strbuf *sb, const char *from, const char *to)
  85. {
  86. char *out;
  87. int len;
  88. if (same_encoding(from, to))
  89. return 0;
  90. out = reencode_string_len(sb->buf, sb->len, to, from, &len);
  91. if (!out)
  92. return -1;
  93. strbuf_attach(sb, out, len, len);
  94. return 0;
  95. }
  96. void strbuf_tolower(struct strbuf *sb)
  97. {
  98. char *p = sb->buf, *end = sb->buf + sb->len;
  99. for (; p < end; p++)
  100. *p = tolower(*p);
  101. }
  102. struct strbuf **strbuf_split_buf(const char *str, size_t slen,
  103. int terminator, int max)
  104. {
  105. struct strbuf **ret = NULL;
  106. size_t nr = 0, alloc = 0;
  107. struct strbuf *t;
  108. while (slen) {
  109. int len = slen;
  110. if (max <= 0 || nr + 1 < max) {
  111. const char *end = memchr(str, terminator, slen);
  112. if (end)
  113. len = end - str + 1;
  114. }
  115. t = xmalloc(sizeof(struct strbuf));
  116. strbuf_init(t, len);
  117. strbuf_add(t, str, len);
  118. ALLOC_GROW(ret, nr + 2, alloc);
  119. ret[nr++] = t;
  120. str += len;
  121. slen -= len;
  122. }
  123. ALLOC_GROW(ret, nr + 1, alloc); /* In case string was empty */
  124. ret[nr] = NULL;
  125. return ret;
  126. }
  127. void strbuf_list_free(struct strbuf **sbs)
  128. {
  129. struct strbuf **s = sbs;
  130. while (*s) {
  131. strbuf_release(*s);
  132. free(*s++);
  133. }
  134. free(sbs);
  135. }
  136. int strbuf_cmp(const struct strbuf *a, const struct strbuf *b)
  137. {
  138. int len = a->len < b->len ? a->len: b->len;
  139. int cmp = memcmp(a->buf, b->buf, len);
  140. if (cmp)
  141. return cmp;
  142. return a->len < b->len ? -1: a->len != b->len;
  143. }
  144. void strbuf_splice(struct strbuf *sb, size_t pos, size_t len,
  145. const void *data, size_t dlen)
  146. {
  147. if (unsigned_add_overflows(pos, len))
  148. die("you want to use way too much memory");
  149. if (pos > sb->len)
  150. die("`pos' is too far after the end of the buffer");
  151. if (pos + len > sb->len)
  152. die("`pos + len' is too far after the end of the buffer");
  153. if (dlen >= len)
  154. strbuf_grow(sb, dlen - len);
  155. memmove(sb->buf + pos + dlen,
  156. sb->buf + pos + len,
  157. sb->len - pos - len);
  158. memcpy(sb->buf + pos, data, dlen);
  159. strbuf_setlen(sb, sb->len + dlen - len);
  160. }
  161. void strbuf_insert(struct strbuf *sb, size_t pos, const void *data, size_t len)
  162. {
  163. strbuf_splice(sb, pos, 0, data, len);
  164. }
  165. void strbuf_remove(struct strbuf *sb, size_t pos, size_t len)
  166. {
  167. strbuf_splice(sb, pos, len, NULL, 0);
  168. }
  169. void strbuf_add(struct strbuf *sb, const void *data, size_t len)
  170. {
  171. strbuf_grow(sb, len);
  172. memcpy(sb->buf + sb->len, data, len);
  173. strbuf_setlen(sb, sb->len + len);
  174. }
  175. void strbuf_adddup(struct strbuf *sb, size_t pos, size_t len)
  176. {
  177. strbuf_grow(sb, len);
  178. memcpy(sb->buf + sb->len, sb->buf + pos, len);
  179. strbuf_setlen(sb, sb->len + len);
  180. }
  181. void strbuf_addchars(struct strbuf *sb, int c, size_t n)
  182. {
  183. strbuf_grow(sb, n);
  184. memset(sb->buf + sb->len, c, n);
  185. strbuf_setlen(sb, sb->len + n);
  186. }
  187. void strbuf_addf(struct strbuf *sb, const char *fmt, ...)
  188. {
  189. va_list ap;
  190. va_start(ap, fmt);
  191. strbuf_vaddf(sb, fmt, ap);
  192. va_end(ap);
  193. }
  194. static void add_lines(struct strbuf *out,
  195. const char *prefix1,
  196. const char *prefix2,
  197. const char *buf, size_t size)
  198. {
  199. while (size) {
  200. const char *prefix;
  201. const char *next = memchr(buf, '\n', size);
  202. next = next ? (next + 1) : (buf + size);
  203. prefix = ((prefix2 && (buf[0] == '\n' || buf[0] == '\t'))
  204. ? prefix2 : prefix1);
  205. strbuf_addstr(out, prefix);
  206. strbuf_add(out, buf, next - buf);
  207. size -= next - buf;
  208. buf = next;
  209. }
  210. strbuf_complete_line(out);
  211. }
  212. void strbuf_add_commented_lines(struct strbuf *out, const char *buf, size_t size)
  213. {
  214. static char prefix1[3];
  215. static char prefix2[2];
  216. if (prefix1[0] != comment_line_char) {
  217. xsnprintf(prefix1, sizeof(prefix1), "%c ", comment_line_char);
  218. xsnprintf(prefix2, sizeof(prefix2), "%c", comment_line_char);
  219. }
  220. add_lines(out, prefix1, prefix2, buf, size);
  221. }
  222. void strbuf_commented_addf(struct strbuf *sb, const char *fmt, ...)
  223. {
  224. va_list params;
  225. struct strbuf buf = STRBUF_INIT;
  226. int incomplete_line = sb->len && sb->buf[sb->len - 1] != '\n';
  227. va_start(params, fmt);
  228. strbuf_vaddf(&buf, fmt, params);
  229. va_end(params);
  230. strbuf_add_commented_lines(sb, buf.buf, buf.len);
  231. if (incomplete_line)
  232. sb->buf[--sb->len] = '\0';
  233. strbuf_release(&buf);
  234. }
  235. void strbuf_vaddf(struct strbuf *sb, const char *fmt, va_list ap)
  236. {
  237. int len;
  238. va_list cp;
  239. if (!strbuf_avail(sb))
  240. strbuf_grow(sb, 64);
  241. va_copy(cp, ap);
  242. len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, cp);
  243. va_end(cp);
  244. if (len < 0)
  245. die("BUG: your vsnprintf is broken (returned %d)", len);
  246. if (len > strbuf_avail(sb)) {
  247. strbuf_grow(sb, len);
  248. len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap);
  249. if (len > strbuf_avail(sb))
  250. die("BUG: your vsnprintf is broken (insatiable)");
  251. }
  252. strbuf_setlen(sb, sb->len + len);
  253. }
  254. void strbuf_expand(struct strbuf *sb, const char *format, expand_fn_t fn,
  255. void *context)
  256. {
  257. for (;;) {
  258. const char *percent;
  259. size_t consumed;
  260. percent = strchrnul(format, '%');
  261. strbuf_add(sb, format, percent - format);
  262. if (!*percent)
  263. break;
  264. format = percent + 1;
  265. if (*format == '%') {
  266. strbuf_addch(sb, '%');
  267. format++;
  268. continue;
  269. }
  270. consumed = fn(sb, format, context);
  271. if (consumed)
  272. format += consumed;
  273. else
  274. strbuf_addch(sb, '%');
  275. }
  276. }
  277. size_t strbuf_expand_dict_cb(struct strbuf *sb, const char *placeholder,
  278. void *context)
  279. {
  280. struct strbuf_expand_dict_entry *e = context;
  281. size_t len;
  282. for (; e->placeholder && (len = strlen(e->placeholder)); e++) {
  283. if (!strncmp(placeholder, e->placeholder, len)) {
  284. if (e->value)
  285. strbuf_addstr(sb, e->value);
  286. return len;
  287. }
  288. }
  289. return 0;
  290. }
  291. void strbuf_addbuf_percentquote(struct strbuf *dst, const struct strbuf *src)
  292. {
  293. int i, len = src->len;
  294. for (i = 0; i < len; i++) {
  295. if (src->buf[i] == '%')
  296. strbuf_addch(dst, '%');
  297. strbuf_addch(dst, src->buf[i]);
  298. }
  299. }
  300. size_t strbuf_fread(struct strbuf *sb, size_t size, FILE *f)
  301. {
  302. size_t res;
  303. size_t oldalloc = sb->alloc;
  304. strbuf_grow(sb, size);
  305. res = fread(sb->buf + sb->len, 1, size, f);
  306. if (res > 0)
  307. strbuf_setlen(sb, sb->len + res);
  308. else if (oldalloc == 0)
  309. strbuf_release(sb);
  310. return res;
  311. }
  312. ssize_t strbuf_read(struct strbuf *sb, int fd, size_t hint)
  313. {
  314. size_t oldlen = sb->len;
  315. size_t oldalloc = sb->alloc;
  316. strbuf_grow(sb, hint ? hint : 8192);
  317. for (;;) {
  318. ssize_t want = sb->alloc - sb->len - 1;
  319. ssize_t got = read_in_full(fd, sb->buf + sb->len, want);
  320. if (got < 0) {
  321. if (oldalloc == 0)
  322. strbuf_release(sb);
  323. else
  324. strbuf_setlen(sb, oldlen);
  325. return -1;
  326. }
  327. sb->len += got;
  328. if (got < want)
  329. break;
  330. strbuf_grow(sb, 8192);
  331. }
  332. sb->buf[sb->len] = '\0';
  333. return sb->len - oldlen;
  334. }
  335. #define STRBUF_MAXLINK (2*PATH_MAX)
  336. int strbuf_readlink(struct strbuf *sb, const char *path, size_t hint)
  337. {
  338. size_t oldalloc = sb->alloc;
  339. if (hint < 32)
  340. hint = 32;
  341. while (hint < STRBUF_MAXLINK) {
  342. int len;
  343. strbuf_grow(sb, hint);
  344. len = readlink(path, sb->buf, hint);
  345. if (len < 0) {
  346. if (errno != ERANGE)
  347. break;
  348. } else if (len < hint) {
  349. strbuf_setlen(sb, len);
  350. return 0;
  351. }
  352. /* .. the buffer was too small - try again */
  353. hint *= 2;
  354. }
  355. if (oldalloc == 0)
  356. strbuf_release(sb);
  357. return -1;
  358. }
  359. int strbuf_getcwd(struct strbuf *sb)
  360. {
  361. size_t oldalloc = sb->alloc;
  362. size_t guessed_len = 128;
  363. for (;; guessed_len *= 2) {
  364. strbuf_grow(sb, guessed_len);
  365. if (getcwd(sb->buf, sb->alloc)) {
  366. strbuf_setlen(sb, strlen(sb->buf));
  367. return 0;
  368. }
  369. if (errno != ERANGE)
  370. break;
  371. }
  372. if (oldalloc == 0)
  373. strbuf_release(sb);
  374. else
  375. strbuf_reset(sb);
  376. return -1;
  377. }
  378. #ifdef HAVE_GETDELIM
  379. int strbuf_getwholeline(struct strbuf *sb, FILE *fp, int term)
  380. {
  381. ssize_t r;
  382. if (feof(fp))
  383. return EOF;
  384. strbuf_reset(sb);
  385. /* Translate slopbuf to NULL, as we cannot call realloc on it */
  386. if (!sb->alloc)
  387. sb->buf = NULL;
  388. r = getdelim(&sb->buf, &sb->alloc, term, fp);
  389. if (r > 0) {
  390. sb->len = r;
  391. return 0;
  392. }
  393. assert(r == -1);
  394. /*
  395. * Normally we would have called xrealloc, which will try to free
  396. * memory and recover. But we have no way to tell getdelim() to do so.
  397. * Worse, we cannot try to recover ENOMEM ourselves, because we have
  398. * no idea how many bytes were read by getdelim.
  399. *
  400. * Dying here is reasonable. It mirrors what xrealloc would do on
  401. * catastrophic memory failure. We skip the opportunity to free pack
  402. * memory and retry, but that's unlikely to help for a malloc small
  403. * enough to hold a single line of input, anyway.
  404. */
  405. if (errno == ENOMEM)
  406. die("Out of memory, getdelim failed");
  407. /* Restore slopbuf that we moved out of the way before */
  408. if (!sb->buf)
  409. strbuf_init(sb, 0);
  410. return EOF;
  411. }
  412. #else
  413. int strbuf_getwholeline(struct strbuf *sb, FILE *fp, int term)
  414. {
  415. int ch;
  416. if (feof(fp))
  417. return EOF;
  418. strbuf_reset(sb);
  419. flockfile(fp);
  420. while ((ch = getc_unlocked(fp)) != EOF) {
  421. if (!strbuf_avail(sb))
  422. strbuf_grow(sb, 1);
  423. sb->buf[sb->len++] = ch;
  424. if (ch == term)
  425. break;
  426. }
  427. funlockfile(fp);
  428. if (ch == EOF && sb->len == 0)
  429. return EOF;
  430. sb->buf[sb->len] = '\0';
  431. return 0;
  432. }
  433. #endif
  434. int strbuf_getline(struct strbuf *sb, FILE *fp, int term)
  435. {
  436. if (strbuf_getwholeline(sb, fp, term))
  437. return EOF;
  438. if (sb->buf[sb->len-1] == term)
  439. strbuf_setlen(sb, sb->len-1);
  440. return 0;
  441. }
  442. int strbuf_getwholeline_fd(struct strbuf *sb, int fd, int term)
  443. {
  444. strbuf_reset(sb);
  445. while (1) {
  446. char ch;
  447. ssize_t len = xread(fd, &ch, 1);
  448. if (len <= 0)
  449. return EOF;
  450. strbuf_addch(sb, ch);
  451. if (ch == term)
  452. break;
  453. }
  454. return 0;
  455. }
  456. ssize_t strbuf_read_file(struct strbuf *sb, const char *path, size_t hint)
  457. {
  458. int fd;
  459. ssize_t len;
  460. fd = open(path, O_RDONLY);
  461. if (fd < 0)
  462. return -1;
  463. len = strbuf_read(sb, fd, hint);
  464. close(fd);
  465. if (len < 0)
  466. return -1;
  467. return len;
  468. }
  469. void strbuf_add_lines(struct strbuf *out, const char *prefix,
  470. const char *buf, size_t size)
  471. {
  472. add_lines(out, prefix, NULL, buf, size);
  473. }
  474. void strbuf_addstr_xml_quoted(struct strbuf *buf, const char *s)
  475. {
  476. while (*s) {
  477. size_t len = strcspn(s, "\"<>&");
  478. strbuf_add(buf, s, len);
  479. s += len;
  480. switch (*s) {
  481. case '"':
  482. strbuf_addstr(buf, "&quot;");
  483. break;
  484. case '<':
  485. strbuf_addstr(buf, "&lt;");
  486. break;
  487. case '>':
  488. strbuf_addstr(buf, "&gt;");
  489. break;
  490. case '&':
  491. strbuf_addstr(buf, "&amp;");
  492. break;
  493. case 0:
  494. return;
  495. }
  496. s++;
  497. }
  498. }
  499. static int is_rfc3986_reserved(char ch)
  500. {
  501. switch (ch) {
  502. case '!': case '*': case '\'': case '(': case ')': case ';':
  503. case ':': case '@': case '&': case '=': case '+': case '$':
  504. case ',': case '/': case '?': case '#': case '[': case ']':
  505. return 1;
  506. }
  507. return 0;
  508. }
  509. static int is_rfc3986_unreserved(char ch)
  510. {
  511. return isalnum(ch) ||
  512. ch == '-' || ch == '_' || ch == '.' || ch == '~';
  513. }
  514. static void strbuf_add_urlencode(struct strbuf *sb, const char *s, size_t len,
  515. int reserved)
  516. {
  517. strbuf_grow(sb, len);
  518. while (len--) {
  519. char ch = *s++;
  520. if (is_rfc3986_unreserved(ch) ||
  521. (!reserved && is_rfc3986_reserved(ch)))
  522. strbuf_addch(sb, ch);
  523. else
  524. strbuf_addf(sb, "%%%02x", ch);
  525. }
  526. }
  527. void strbuf_addstr_urlencode(struct strbuf *sb, const char *s,
  528. int reserved)
  529. {
  530. strbuf_add_urlencode(sb, s, strlen(s), reserved);
  531. }
  532. void strbuf_humanise_bytes(struct strbuf *buf, off_t bytes)
  533. {
  534. if (bytes > 1 << 30) {
  535. strbuf_addf(buf, "%u.%2.2u GiB",
  536. (int)(bytes >> 30),
  537. (int)(bytes & ((1 << 30) - 1)) / 10737419);
  538. } else if (bytes > 1 << 20) {
  539. int x = bytes + 5243; /* for rounding */
  540. strbuf_addf(buf, "%u.%2.2u MiB",
  541. x >> 20, ((x & ((1 << 20) - 1)) * 100) >> 20);
  542. } else if (bytes > 1 << 10) {
  543. int x = bytes + 5; /* for rounding */
  544. strbuf_addf(buf, "%u.%2.2u KiB",
  545. x >> 10, ((x & ((1 << 10) - 1)) * 100) >> 10);
  546. } else {
  547. strbuf_addf(buf, "%u bytes", (int)bytes);
  548. }
  549. }
  550. void strbuf_add_absolute_path(struct strbuf *sb, const char *path)
  551. {
  552. if (!*path)
  553. die("The empty string is not a valid path");
  554. if (!is_absolute_path(path)) {
  555. struct stat cwd_stat, pwd_stat;
  556. size_t orig_len = sb->len;
  557. char *cwd = xgetcwd();
  558. char *pwd = getenv("PWD");
  559. if (pwd && strcmp(pwd, cwd) &&
  560. !stat(cwd, &cwd_stat) &&
  561. (cwd_stat.st_dev || cwd_stat.st_ino) &&
  562. !stat(pwd, &pwd_stat) &&
  563. pwd_stat.st_dev == cwd_stat.st_dev &&
  564. pwd_stat.st_ino == cwd_stat.st_ino)
  565. strbuf_addstr(sb, pwd);
  566. else
  567. strbuf_addstr(sb, cwd);
  568. if (sb->len > orig_len && !is_dir_sep(sb->buf[sb->len - 1]))
  569. strbuf_addch(sb, '/');
  570. free(cwd);
  571. }
  572. strbuf_addstr(sb, path);
  573. }
  574. int printf_ln(const char *fmt, ...)
  575. {
  576. int ret;
  577. va_list ap;
  578. va_start(ap, fmt);
  579. ret = vprintf(fmt, ap);
  580. va_end(ap);
  581. if (ret < 0 || putchar('\n') == EOF)
  582. return -1;
  583. return ret + 1;
  584. }
  585. int fprintf_ln(FILE *fp, const char *fmt, ...)
  586. {
  587. int ret;
  588. va_list ap;
  589. va_start(ap, fmt);
  590. ret = vfprintf(fp, fmt, ap);
  591. va_end(ap);
  592. if (ret < 0 || putc('\n', fp) == EOF)
  593. return -1;
  594. return ret + 1;
  595. }
  596. char *xstrdup_tolower(const char *string)
  597. {
  598. char *result;
  599. size_t len, i;
  600. len = strlen(string);
  601. result = xmalloc(len + 1);
  602. for (i = 0; i < len; i++)
  603. result[i] = tolower(string[i]);
  604. result[i] = '\0';
  605. return result;
  606. }
  607. char *xstrvfmt(const char *fmt, va_list ap)
  608. {
  609. struct strbuf buf = STRBUF_INIT;
  610. strbuf_vaddf(&buf, fmt, ap);
  611. return strbuf_detach(&buf, NULL);
  612. }
  613. char *xstrfmt(const char *fmt, ...)
  614. {
  615. va_list ap;
  616. char *ret;
  617. va_start(ap, fmt);
  618. ret = xstrvfmt(fmt, ap);
  619. va_end(ap);
  620. return ret;
  621. }
  622. void strbuf_addftime(struct strbuf *sb, const char *fmt, const struct tm *tm)
  623. {
  624. size_t hint = 128;
  625. size_t len;
  626. if (!*fmt)
  627. return;
  628. strbuf_grow(sb, hint);
  629. len = strftime(sb->buf + sb->len, sb->alloc - sb->len, fmt, tm);
  630. if (!len) {
  631. /*
  632. * strftime reports "0" if it could not fit the result in the buffer.
  633. * Unfortunately, it also reports "0" if the requested time string
  634. * takes 0 bytes. So our strategy is to munge the format so that the
  635. * output contains at least one character, and then drop the extra
  636. * character before returning.
  637. */
  638. struct strbuf munged_fmt = STRBUF_INIT;
  639. strbuf_addf(&munged_fmt, "%s ", fmt);
  640. while (!len) {
  641. hint *= 2;
  642. strbuf_grow(sb, hint);
  643. len = strftime(sb->buf + sb->len, sb->alloc - sb->len,
  644. munged_fmt.buf, tm);
  645. }
  646. strbuf_release(&munged_fmt);
  647. len--; /* drop munged space */
  648. }
  649. strbuf_setlen(sb, sb->len + len);
  650. }
  651. void strbuf_add_unique_abbrev(struct strbuf *sb, const unsigned char *sha1,
  652. int abbrev_len)
  653. {
  654. int r;
  655. strbuf_grow(sb, GIT_SHA1_HEXSZ + 1);
  656. r = find_unique_abbrev_r(sb->buf + sb->len, sha1, abbrev_len);
  657. strbuf_setlen(sb, sb->len + r);
  658. }
  659. /*
  660. * Returns the length of a line, without trailing spaces.
  661. *
  662. * If the line ends with newline, it will be removed too.
  663. */
  664. static size_t cleanup(char *line, size_t len)
  665. {
  666. while (len) {
  667. unsigned char c = line[len - 1];
  668. if (!isspace(c))
  669. break;
  670. len--;
  671. }
  672. return len;
  673. }
  674. /*
  675. * Remove empty lines from the beginning and end
  676. * and also trailing spaces from every line.
  677. *
  678. * Turn multiple consecutive empty lines between paragraphs
  679. * into just one empty line.
  680. *
  681. * If the input has only empty lines and spaces,
  682. * no output will be produced.
  683. *
  684. * If last line does not have a newline at the end, one is added.
  685. *
  686. * Enable skip_comments to skip every line starting with comment
  687. * character.
  688. */
  689. void strbuf_stripspace(struct strbuf *sb, int skip_comments)
  690. {
  691. int empties = 0;
  692. size_t i, j, len, newlen;
  693. char *eol;
  694. /* We may have to add a newline. */
  695. strbuf_grow(sb, 1);
  696. for (i = j = 0; i < sb->len; i += len, j += newlen) {
  697. eol = memchr(sb->buf + i, '\n', sb->len - i);
  698. len = eol ? eol - (sb->buf + i) + 1 : sb->len - i;
  699. if (skip_comments && len && sb->buf[i] == comment_line_char) {
  700. newlen = 0;
  701. continue;
  702. }
  703. newlen = cleanup(sb->buf + i, len);
  704. /* Not just an empty line? */
  705. if (newlen) {
  706. if (empties > 0 && j > 0)
  707. sb->buf[j++] = '\n';
  708. empties = 0;
  709. memmove(sb->buf + j, sb->buf + i, newlen);
  710. sb->buf[newlen + j++] = '\n';
  711. } else {
  712. empties++;
  713. }
  714. }
  715. strbuf_setlen(sb, j);
  716. }