strbuf.c 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  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_grow(struct strbuf *sb, size_t extra)
  39. {
  40. if (sb->len + extra + 1 <= sb->len)
  41. die("you want to use way too much memory");
  42. if (!sb->alloc)
  43. sb->buf = NULL;
  44. ALLOC_GROW(sb->buf, sb->len + extra + 1, sb->alloc);
  45. }
  46. static void strbuf_splice(struct strbuf *sb, size_t pos, size_t len,
  47. const void *data, size_t dlen)
  48. {
  49. if (pos + len < pos)
  50. die("you want to use way too much memory");
  51. if (pos > sb->len)
  52. die("`pos' is too far after the end of the buffer");
  53. if (pos + len > sb->len)
  54. die("`pos + len' is too far after the end of the buffer");
  55. if (dlen >= len)
  56. strbuf_grow(sb, dlen - len);
  57. memmove(sb->buf + pos + dlen,
  58. sb->buf + pos + len,
  59. sb->len - pos - len);
  60. memcpy(sb->buf + pos, data, dlen);
  61. strbuf_setlen(sb, sb->len + dlen - len);
  62. }
  63. void strbuf_remove(struct strbuf *sb, size_t pos, size_t len)
  64. {
  65. strbuf_splice(sb, pos, len, NULL, 0);
  66. }
  67. void strbuf_add(struct strbuf *sb, const void *data, size_t len)
  68. {
  69. strbuf_grow(sb, len);
  70. memcpy(sb->buf + sb->len, data, len);
  71. strbuf_setlen(sb, sb->len + len);
  72. }
  73. void strbuf_addf(struct strbuf *sb, const char *fmt, ...)
  74. {
  75. int len;
  76. va_list ap;
  77. if (!strbuf_avail(sb))
  78. strbuf_grow(sb, 64);
  79. va_start(ap, fmt);
  80. len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap);
  81. va_end(ap);
  82. if (len < 0)
  83. die("your vsnprintf is broken");
  84. if (len > strbuf_avail(sb)) {
  85. strbuf_grow(sb, len);
  86. va_start(ap, fmt);
  87. len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap);
  88. va_end(ap);
  89. if (len > strbuf_avail(sb)) {
  90. die("this should not happen, your snprintf is broken");
  91. }
  92. }
  93. strbuf_setlen(sb, sb->len + len);
  94. }
  95. ssize_t strbuf_read(struct strbuf *sb, int fd, ssize_t hint)
  96. {
  97. size_t oldlen = sb->len;
  98. size_t oldalloc = sb->alloc;
  99. strbuf_grow(sb, hint ? hint : 8192);
  100. for (;;) {
  101. ssize_t cnt;
  102. cnt = read(fd, sb->buf + sb->len, sb->alloc - sb->len - 1);
  103. if (cnt < 0) {
  104. if (oldalloc == 0)
  105. strbuf_release(sb);
  106. else
  107. strbuf_setlen(sb, oldlen);
  108. return -1;
  109. }
  110. if (!cnt)
  111. break;
  112. sb->len += cnt;
  113. strbuf_grow(sb, 8192);
  114. }
  115. sb->buf[sb->len] = '\0';
  116. return sb->len - oldlen;
  117. }