Upgrade libgit2
[TortoiseGit.git] / src / TortoisePlink / utils / strbuf.c
blob9a2ef80f6fee3dbe762607d9c8f3697f423f12f5
1 /*
2 * Functions to work with strbufs.
3 */
5 #include "defs.h"
6 #include "misc.h"
7 #include "utils/utils.h"
9 struct strbuf_impl {
10 size_t size;
11 struct strbuf visible;
12 bool nm; /* true if we insist on non-moving buffer resizes */
15 #define STRBUF_SET_UPTR(buf) \
16 ((buf)->visible.u = (unsigned char *)(buf)->visible.s)
17 #define STRBUF_SET_PTR(buf, ptr) \
18 ((buf)->visible.s = (ptr), STRBUF_SET_UPTR(buf))
20 void *strbuf_append(strbuf *buf_o, size_t len)
22 struct strbuf_impl *buf = container_of(buf_o, struct strbuf_impl, visible);
23 char *toret;
24 sgrowarray_general(
25 buf->visible.s, buf->size, buf->visible.len + 1, len, buf->nm);
26 STRBUF_SET_UPTR(buf);
27 toret = buf->visible.s + buf->visible.len;
28 buf->visible.len += len;
29 buf->visible.s[buf->visible.len] = '\0';
30 return toret;
33 void strbuf_shrink_to(strbuf *buf, size_t new_len)
35 assert(new_len <= buf->len);
36 buf->len = new_len;
37 buf->s[buf->len] = '\0';
40 void strbuf_shrink_by(strbuf *buf, size_t amount_to_remove)
42 assert(amount_to_remove <= buf->len);
43 buf->len -= amount_to_remove;
44 buf->s[buf->len] = '\0';
47 bool strbuf_chomp(strbuf *buf, char char_to_remove)
49 if (buf->len > 0 && buf->s[buf->len-1] == char_to_remove) {
50 strbuf_shrink_by(buf, 1);
51 return true;
53 return false;
56 static void strbuf_BinarySink_write(
57 BinarySink *bs, const void *data, size_t len)
59 strbuf *buf_o = BinarySink_DOWNCAST(bs, strbuf);
60 memcpy(strbuf_append(buf_o, len), data, len);
63 static void strbuf_BinarySink_writefmtv(
64 BinarySink *bs, const char *fmt, va_list ap)
66 strbuf *buf_o = BinarySink_DOWNCAST(bs, strbuf);
67 struct strbuf_impl *buf = container_of(buf_o, struct strbuf_impl, visible);
68 STRBUF_SET_PTR(buf, dupvprintf_inner(buf->visible.s, buf->visible.len,
69 &buf->size, fmt, ap));
70 buf->visible.len += strlen(buf->visible.s + buf->visible.len);
73 static strbuf *strbuf_new_general(bool nm)
75 struct strbuf_impl *buf = snew(struct strbuf_impl);
76 BinarySink_INIT(&buf->visible, strbuf_BinarySink_write);
77 buf->visible.binarysink_->writefmtv = strbuf_BinarySink_writefmtv;
78 buf->visible.len = 0;
79 buf->size = 512;
80 buf->nm = nm;
81 STRBUF_SET_PTR(buf, snewn(buf->size, char));
82 *buf->visible.s = '\0';
83 return &buf->visible;
85 strbuf *strbuf_new(void) { return strbuf_new_general(false); }
86 strbuf *strbuf_new_nm(void) { return strbuf_new_general(true); }
87 void strbuf_free(strbuf *buf_o)
89 struct strbuf_impl *buf = container_of(buf_o, struct strbuf_impl, visible);
90 if (buf->visible.s) {
91 smemclr(buf->visible.s, buf->size);
92 sfree(buf->visible.s);
94 sfree(buf);
96 char *strbuf_to_str(strbuf *buf_o)
98 struct strbuf_impl *buf = container_of(buf_o, struct strbuf_impl, visible);
99 char *ret = buf->visible.s;
100 sfree(buf);
101 return ret;
103 strbuf *strbuf_new_for_agent_query(void)
105 strbuf *buf = strbuf_new();
106 strbuf_append(buf, 4);
107 return buf;
109 void strbuf_finalise_agent_query(strbuf *buf_o)
111 struct strbuf_impl *buf = container_of(buf_o, struct strbuf_impl, visible);
112 assert(buf->visible.len >= 5);
113 PUT_32BIT_MSB_FIRST(buf->visible.u, buf->visible.len - 4);
116 strbuf *strbuf_dup(ptrlen string)
118 strbuf *buf = strbuf_new();
119 put_datapl(buf, string);
120 return buf;
123 strbuf *strbuf_dup_nm(ptrlen string)
125 strbuf *buf = strbuf_new_nm();
126 put_datapl(buf, string);
127 return buf;