Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mRemoteNG/PuTTYNG.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'utils/strbuf.c')
-rw-r--r--utils/strbuf.c128
1 files changed, 128 insertions, 0 deletions
diff --git a/utils/strbuf.c b/utils/strbuf.c
new file mode 100644
index 00000000..c636de47
--- /dev/null
+++ b/utils/strbuf.c
@@ -0,0 +1,128 @@
+/*
+ * Functions to work with strbufs.
+ */
+
+#include "defs.h"
+#include "misc.h"
+#include "utils/utils.h"
+
+struct strbuf_impl {
+ size_t size;
+ struct strbuf visible;
+ bool nm; /* true if we insist on non-moving buffer resizes */
+};
+
+#define STRBUF_SET_UPTR(buf) \
+ ((buf)->visible.u = (unsigned char *)(buf)->visible.s)
+#define STRBUF_SET_PTR(buf, ptr) \
+ ((buf)->visible.s = (ptr), STRBUF_SET_UPTR(buf))
+
+void *strbuf_append(strbuf *buf_o, size_t len)
+{
+ struct strbuf_impl *buf = container_of(buf_o, struct strbuf_impl, visible);
+ char *toret;
+ sgrowarray_general(
+ buf->visible.s, buf->size, buf->visible.len + 1, len, buf->nm);
+ STRBUF_SET_UPTR(buf);
+ toret = buf->visible.s + buf->visible.len;
+ buf->visible.len += len;
+ buf->visible.s[buf->visible.len] = '\0';
+ return toret;
+}
+
+void strbuf_shrink_to(strbuf *buf, size_t new_len)
+{
+ assert(new_len <= buf->len);
+ buf->len = new_len;
+ buf->s[buf->len] = '\0';
+}
+
+void strbuf_shrink_by(strbuf *buf, size_t amount_to_remove)
+{
+ assert(amount_to_remove <= buf->len);
+ buf->len -= amount_to_remove;
+ buf->s[buf->len] = '\0';
+}
+
+bool strbuf_chomp(strbuf *buf, char char_to_remove)
+{
+ if (buf->len > 0 && buf->s[buf->len-1] == char_to_remove) {
+ strbuf_shrink_by(buf, 1);
+ return true;
+ }
+ return false;
+}
+
+static void strbuf_BinarySink_write(
+ BinarySink *bs, const void *data, size_t len)
+{
+ strbuf *buf_o = BinarySink_DOWNCAST(bs, strbuf);
+ memcpy(strbuf_append(buf_o, len), data, len);
+}
+
+static void strbuf_BinarySink_writefmtv(
+ BinarySink *bs, const char *fmt, va_list ap)
+{
+ strbuf *buf_o = BinarySink_DOWNCAST(bs, strbuf);
+ struct strbuf_impl *buf = container_of(buf_o, struct strbuf_impl, visible);
+ STRBUF_SET_PTR(buf, dupvprintf_inner(buf->visible.s, buf->visible.len,
+ &buf->size, fmt, ap));
+ buf->visible.len += strlen(buf->visible.s + buf->visible.len);
+}
+
+static strbuf *strbuf_new_general(bool nm)
+{
+ struct strbuf_impl *buf = snew(struct strbuf_impl);
+ BinarySink_INIT(&buf->visible, strbuf_BinarySink_write);
+ buf->visible.binarysink_->writefmtv = strbuf_BinarySink_writefmtv;
+ buf->visible.len = 0;
+ buf->size = 512;
+ buf->nm = nm;
+ STRBUF_SET_PTR(buf, snewn(buf->size, char));
+ *buf->visible.s = '\0';
+ return &buf->visible;
+}
+strbuf *strbuf_new(void) { return strbuf_new_general(false); }
+strbuf *strbuf_new_nm(void) { return strbuf_new_general(true); }
+void strbuf_free(strbuf *buf_o)
+{
+ struct strbuf_impl *buf = container_of(buf_o, struct strbuf_impl, visible);
+ if (buf->visible.s) {
+ smemclr(buf->visible.s, buf->size);
+ sfree(buf->visible.s);
+ }
+ sfree(buf);
+}
+char *strbuf_to_str(strbuf *buf_o)
+{
+ struct strbuf_impl *buf = container_of(buf_o, struct strbuf_impl, visible);
+ char *ret = buf->visible.s;
+ sfree(buf);
+ return ret;
+}
+strbuf *strbuf_new_for_agent_query(void)
+{
+ strbuf *buf = strbuf_new();
+ strbuf_append(buf, 4);
+ return buf;
+}
+void strbuf_finalise_agent_query(strbuf *buf_o)
+{
+ struct strbuf_impl *buf = container_of(buf_o, struct strbuf_impl, visible);
+ assert(buf->visible.len >= 5);
+ PUT_32BIT_MSB_FIRST(buf->visible.u, buf->visible.len - 4);
+}
+
+strbuf *strbuf_dup(ptrlen string)
+{
+ strbuf *buf = strbuf_new();
+ put_datapl(buf, string);
+ return buf;
+}
+
+strbuf *strbuf_dup_nm(ptrlen string)
+{
+ strbuf *buf = strbuf_new_nm();
+ put_datapl(buf, string);
+ return buf;
+}