strbuf.c 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. #include "cache.h"
  2. #include <linux/kernel.h>
  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. * Used as the default ->buf value, so that people can always assume
  13. * buf is non NULL and ->buf is NUL terminated even for a freshly
  14. * initialized strbuf.
  15. */
  16. char strbuf_slopbuf[1];
  17. void strbuf_init(struct strbuf *sb, ssize_t hint)
  18. {
  19. sb->alloc = sb->len = 0;
  20. sb->buf = strbuf_slopbuf;
  21. if (hint)
  22. strbuf_grow(sb, hint);
  23. }
  24. void strbuf_release(struct strbuf *sb)
  25. {
  26. if (sb->alloc) {
  27. zfree(&sb->buf);
  28. strbuf_init(sb, 0);
  29. }
  30. }
  31. char *strbuf_detach(struct strbuf *sb, size_t *sz)
  32. {
  33. char *res = sb->alloc ? sb->buf : NULL;
  34. if (sz)
  35. *sz = sb->len;
  36. strbuf_init(sb, 0);
  37. return res;
  38. }
  39. void strbuf_grow(struct strbuf *sb, size_t extra)
  40. {
  41. if (sb->len + extra + 1 <= sb->len)
  42. die("you want to use way too much memory");
  43. if (!sb->alloc)
  44. sb->buf = NULL;
  45. ALLOC_GROW(sb->buf, sb->len + extra + 1, sb->alloc);
  46. }
  47. void strbuf_addch(struct strbuf *sb, int c)
  48. {
  49. strbuf_grow(sb, 1);
  50. sb->buf[sb->len++] = c;
  51. sb->buf[sb->len] = '\0';
  52. }
  53. void strbuf_add(struct strbuf *sb, const void *data, size_t len)
  54. {
  55. strbuf_grow(sb, len);
  56. memcpy(sb->buf + sb->len, data, len);
  57. strbuf_setlen(sb, sb->len + len);
  58. }
  59. static void strbuf_addv(struct strbuf *sb, const char *fmt, va_list ap)
  60. {
  61. int len;
  62. va_list ap_saved;
  63. if (!strbuf_avail(sb))
  64. strbuf_grow(sb, 64);
  65. va_copy(ap_saved, ap);
  66. len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap);
  67. if (len < 0)
  68. die("your vsnprintf is broken");
  69. if (len > strbuf_avail(sb)) {
  70. strbuf_grow(sb, len);
  71. len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap_saved);
  72. va_end(ap_saved);
  73. if (len > strbuf_avail(sb)) {
  74. die("this should not happen, your vsnprintf is broken");
  75. }
  76. }
  77. strbuf_setlen(sb, sb->len + len);
  78. }
  79. void strbuf_addf(struct strbuf *sb, const char *fmt, ...)
  80. {
  81. va_list ap;
  82. va_start(ap, fmt);
  83. strbuf_addv(sb, fmt, ap);
  84. va_end(ap);
  85. }
  86. ssize_t strbuf_read(struct strbuf *sb, int fd, ssize_t hint)
  87. {
  88. size_t oldlen = sb->len;
  89. size_t oldalloc = sb->alloc;
  90. strbuf_grow(sb, hint ? hint : 8192);
  91. for (;;) {
  92. ssize_t cnt;
  93. cnt = read(fd, sb->buf + sb->len, sb->alloc - sb->len - 1);
  94. if (cnt < 0) {
  95. if (oldalloc == 0)
  96. strbuf_release(sb);
  97. else
  98. strbuf_setlen(sb, oldlen);
  99. return -1;
  100. }
  101. if (!cnt)
  102. break;
  103. sb->len += cnt;
  104. strbuf_grow(sb, 8192);
  105. }
  106. sb->buf[sb->len] = '\0';
  107. return sb->len - oldlen;
  108. }