#define REFTABLE_ALLOW_BANNED_ALLOCATORS
#include "basics.h"
#include "reftable-basics.h"
+#include "reftable-error.h"
static void *(*reftable_malloc_ptr)(size_t sz);
static void *(*reftable_realloc_ptr)(void *, size_t);
reftable_free_ptr = free;
}
+void reftable_buf_init(struct reftable_buf *buf)
+{
+ struct reftable_buf empty = REFTABLE_BUF_INIT;
+ *buf = empty;
+}
+
+void reftable_buf_release(struct reftable_buf *buf)
+{
+ reftable_free(buf->buf);
+ reftable_buf_init(buf);
+}
+
+void reftable_buf_reset(struct reftable_buf *buf)
+{
+ if (buf->alloc) {
+ buf->len = 0;
+ buf->buf[0] = '\0';
+ }
+}
+
+int reftable_buf_setlen(struct reftable_buf *buf, size_t len)
+{
+ if (len > buf->len)
+ return -1;
+ if (len == buf->len)
+ return 0;
+ buf->buf[len] = '\0';
+ buf->len = len;
+ return 0;
+}
+
+int reftable_buf_cmp(const struct reftable_buf *a, const struct reftable_buf *b)
+{
+ size_t len = a->len < b->len ? a->len : b->len;
+ if (len) {
+ int cmp = memcmp(a->buf, b->buf, len);
+ if (cmp)
+ return cmp;
+ }
+ return a->len < b->len ? -1 : a->len != b->len;
+}
+
+int reftable_buf_add(struct reftable_buf *buf, const void *data, size_t len)
+{
+ size_t newlen = buf->len + len;
+
+ if (newlen + 1 > buf->alloc) {
+ char *reallocated = buf->buf;
+ REFTABLE_ALLOC_GROW(reallocated, newlen + 1, buf->alloc);
+ if (!reallocated)
+ return REFTABLE_OUT_OF_MEMORY_ERROR;
+ buf->buf = reallocated;
+ }
+
+ memcpy(buf->buf + buf->len, data, len);
+ buf->buf[newlen] = '\0';
+ buf->len = newlen;
+
+ return 0;
+}
+
+int reftable_buf_addstr(struct reftable_buf *buf, const char *s)
+{
+ return reftable_buf_add(buf, s, strlen(s));
+}
+
+char *reftable_buf_detach(struct reftable_buf *buf)
+{
+ char *result = buf->buf;
+ reftable_buf_init(buf);
+ return result;
+}
+
void put_be24(uint8_t *out, uint32_t i)
{
out[0] = (uint8_t)((i >> 16) & 0xff);
#include "system.h"
#include "reftable-basics.h"
+struct reftable_buf {
+ size_t alloc;
+ size_t len;
+ char *buf;
+};
+#define REFTABLE_BUF_INIT { 0 }
+
+/*
+ * Initialize the buffer such that it is ready for use. This is equivalent to
+ * using REFTABLE_BUF_INIT for stack-allocated variables.
+ */
+void reftable_buf_init(struct reftable_buf *buf);
+
+/*
+ * Release memory associated with the buffer. The buffer is reinitialized such
+ * that it can be reused for subsequent operations.
+ */
+void reftable_buf_release(struct reftable_buf *buf);
+
+/*
+ * Reset the buffer such that it is effectively empty, without releasing the
+ * memory that this structure holds on to. This is equivalent to calling
+ * `reftable_buf_setlen(buf, 0)`.
+ */
+void reftable_buf_reset(struct reftable_buf *buf);
+
+/*
+ * Trim the buffer to a shorter length by updating the `len` member and writing
+ * a NUL byte to `buf[len]`. Returns 0 on success, -1 when `len` points outside
+ * of the array.
+ */
+int reftable_buf_setlen(struct reftable_buf *buf, size_t len);
+
+/*
+ * Lexicographically compare the two buffers. Returns 0 when both buffers have
+ * the same contents, -1 when `a` is lexicographically smaller than `b`, and 1
+ * otherwise.
+ */
+int reftable_buf_cmp(const struct reftable_buf *a, const struct reftable_buf *b);
+
+/*
+ * Add the given bytes to the buffer. Returns 0 on success,
+ * REFTABLE_OUT_OF_MEMORY_ERROR on allocation failure.
+ */
+int reftable_buf_add(struct reftable_buf *buf, const void *data, size_t len);
+
+/* Equivalent to `reftable_buf_add(buf, s, strlen(s))`. */
+int reftable_buf_addstr(struct reftable_buf *buf, const char *s);
+
+/*
+ * Detach the buffer from the structure such that the underlying memory is now
+ * owned by the caller. The buffer is reinitialized such that it can be reused
+ * for subsequent operations.
+ */
+char *reftable_buf_detach(struct reftable_buf *buf);
+
/* Bigendian en/decoding of integers */
void put_be24(uint8_t *out, uint32_t i);