strbuf.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. /*
  2. * Functions to work with strbufs.
  3. */
  4. #include "defs.h"
  5. #include "misc.h"
  6. #include "utils/utils.h"
  7. struct strbuf_impl {
  8. size_t size;
  9. struct strbuf visible;
  10. bool nm; /* true if we insist on non-moving buffer resizes */
  11. };
  12. #define STRBUF_SET_UPTR(buf) \
  13. ((buf)->visible.u = (unsigned char *)(buf)->visible.s)
  14. #define STRBUF_SET_PTR(buf, ptr) \
  15. ((buf)->visible.s = (ptr), STRBUF_SET_UPTR(buf))
  16. void *strbuf_append(strbuf *buf_o, size_t len)
  17. {
  18. struct strbuf_impl *buf = container_of(buf_o, struct strbuf_impl, visible);
  19. char *toret;
  20. sgrowarray_general(
  21. buf->visible.s, buf->size, buf->visible.len + 1, len, buf->nm);
  22. STRBUF_SET_UPTR(buf);
  23. toret = buf->visible.s + buf->visible.len;
  24. buf->visible.len += len;
  25. buf->visible.s[buf->visible.len] = '\0';
  26. return toret;
  27. }
  28. void strbuf_shrink_to(strbuf *buf, size_t new_len)
  29. {
  30. assert(new_len <= buf->len);
  31. buf->len = new_len;
  32. buf->s[buf->len] = '\0';
  33. }
  34. void strbuf_shrink_by(strbuf *buf, size_t amount_to_remove)
  35. {
  36. assert(amount_to_remove <= buf->len);
  37. buf->len -= amount_to_remove;
  38. buf->s[buf->len] = '\0';
  39. }
  40. bool strbuf_chomp(strbuf *buf, char char_to_remove)
  41. {
  42. if (buf->len > 0 && buf->s[buf->len-1] == char_to_remove) {
  43. strbuf_shrink_by(buf, 1);
  44. return true;
  45. }
  46. return false;
  47. }
  48. static void strbuf_BinarySink_write(
  49. BinarySink *bs, const void *data, size_t len)
  50. {
  51. strbuf *buf_o = BinarySink_DOWNCAST(bs, strbuf);
  52. memcpy(strbuf_append(buf_o, len), data, len);
  53. }
  54. static void strbuf_BinarySink_writefmtv(
  55. BinarySink *bs, const char *fmt, va_list ap)
  56. {
  57. strbuf *buf_o = BinarySink_DOWNCAST(bs, strbuf);
  58. struct strbuf_impl *buf = container_of(buf_o, struct strbuf_impl, visible);
  59. STRBUF_SET_PTR(buf, dupvprintf_inner(buf->visible.s, buf->visible.len,
  60. &buf->size, fmt, ap));
  61. buf->visible.len += strlen(buf->visible.s + buf->visible.len);
  62. }
  63. static strbuf *strbuf_new_general(bool nm)
  64. {
  65. struct strbuf_impl *buf = snew(struct strbuf_impl);
  66. BinarySink_INIT(&buf->visible, strbuf_BinarySink_write);
  67. buf->visible.binarysink_->writefmtv = strbuf_BinarySink_writefmtv;
  68. buf->visible.len = 0;
  69. buf->size = 512;
  70. buf->nm = nm;
  71. STRBUF_SET_PTR(buf, snewn(buf->size, char));
  72. *buf->visible.s = '\0';
  73. return &buf->visible;
  74. }
  75. strbuf *strbuf_new(void) { return strbuf_new_general(false); }
  76. strbuf *strbuf_new_nm(void) { return strbuf_new_general(true); }
  77. void strbuf_free(strbuf *buf_o)
  78. {
  79. struct strbuf_impl *buf = container_of(buf_o, struct strbuf_impl, visible);
  80. if (buf->visible.s) {
  81. smemclr(buf->visible.s, buf->size);
  82. sfree(buf->visible.s);
  83. }
  84. sfree(buf);
  85. }
  86. char *strbuf_to_str(strbuf *buf_o)
  87. {
  88. struct strbuf_impl *buf = container_of(buf_o, struct strbuf_impl, visible);
  89. char *ret = buf->visible.s;
  90. sfree(buf);
  91. return ret;
  92. }
  93. strbuf *strbuf_new_for_agent_query(void)
  94. {
  95. strbuf *buf = strbuf_new();
  96. strbuf_append(buf, 4);
  97. return buf;
  98. }
  99. void strbuf_finalise_agent_query(strbuf *buf_o)
  100. {
  101. struct strbuf_impl *buf = container_of(buf_o, struct strbuf_impl, visible);
  102. assert(buf->visible.len >= 5);
  103. PUT_32BIT_MSB_FIRST(buf->visible.u, buf->visible.len - 4);
  104. }
  105. strbuf *strbuf_dup(ptrlen string)
  106. {
  107. strbuf *buf = strbuf_new();
  108. put_datapl(buf, string);
  109. return buf;
  110. }
  111. strbuf *strbuf_dup_nm(ptrlen string)
  112. {
  113. strbuf *buf = strbuf_new_nm();
  114. put_datapl(buf, string);
  115. return buf;
  116. }