summaryrefslogtreecommitdiffstats
path: root/lib/dpkg/varbuf.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/dpkg/varbuf.c')
-rw-r--r--lib/dpkg/varbuf.c93
1 files changed, 77 insertions, 16 deletions
diff --git a/lib/dpkg/varbuf.c b/lib/dpkg/varbuf.c
index a5d3d31..5829a6f 100644
--- a/lib/dpkg/varbuf.c
+++ b/lib/dpkg/varbuf.c
@@ -46,10 +46,12 @@ varbuf_init(struct varbuf *v, size_t size)
{
v->used = 0;
v->size = size;
- if (size)
+ if (size) {
v->buf = m_malloc(size);
- else
+ v->buf[0] = '\0';
+ } else {
v->buf = NULL;
+ }
}
void
@@ -83,18 +85,23 @@ varbuf_trunc(struct varbuf *v, size_t used_size)
internerr("varbuf new_used(%zu) > size(%zu)", used_size, v->size);
v->used = used_size;
+ if (v->buf)
+ v->buf[v->used] = '\0';
}
void
varbuf_reset(struct varbuf *v)
{
v->used = 0;
+ if (v->buf)
+ v->buf[0] = '\0';
}
const char *
-varbuf_get_str(struct varbuf *v)
+varbuf_str(struct varbuf *v)
{
- varbuf_end_str(v);
+ if (v->buf == NULL)
+ return "";
return v->buf;
}
@@ -104,7 +111,6 @@ varbuf_set_buf(struct varbuf *v, const void *buf, size_t size)
{
varbuf_reset(v);
varbuf_add_buf(v, buf, size);
- varbuf_end_str(v);
}
void
@@ -116,16 +122,18 @@ varbuf_set_varbuf(struct varbuf *v, struct varbuf *other)
void
varbuf_add_varbuf(struct varbuf *v, const struct varbuf *other)
{
- varbuf_grow(v, other->used);
+ varbuf_grow(v, other->used + 1);
memcpy(v->buf + v->used, other->buf, other->used);
v->used += other->used;
+ v->buf[v->used] = '\0';
}
void
varbuf_add_char(struct varbuf *v, int c)
{
- varbuf_grow(v, 1);
+ varbuf_grow(v, 2);
v->buf[v->used++] = c;
+ v->buf[v->used] = '\0';
}
void
@@ -133,9 +141,10 @@ varbuf_dup_char(struct varbuf *v, int c, size_t n)
{
if (n == 0)
return;
- varbuf_grow(v, n);
+ varbuf_grow(v, n + 1);
memset(v->buf + v->used, c, n);
v->used += n;
+ v->buf[v->used] = '\0';
}
void
@@ -161,16 +170,68 @@ varbuf_add_buf(struct varbuf *v, const void *s, size_t size)
{
if (size == 0)
return;
- varbuf_grow(v, size);
+ varbuf_grow(v, size + 1);
memcpy(v->buf + v->used, s, size);
v->used += size;
+ v->buf[v->used] = '\0';
+}
+
+bool
+varbuf_has_prefix(struct varbuf *v, struct varbuf *prefix)
+{
+ if (prefix->used > v->used)
+ return false;
+
+ if (prefix->used == 0)
+ return true;
+ if (v->used == 0)
+ return false;
+
+ return strncmp(v->buf, prefix->buf, prefix->used) == 0;
+}
+
+bool
+varbuf_has_suffix(struct varbuf *v, struct varbuf *suffix)
+{
+ const char *slice;
+
+ if (suffix->used > v->used)
+ return false;
+
+ if (suffix->used == 0)
+ return true;
+ if (v->used == 0)
+ return false;
+
+ slice = v->buf + v->used - suffix->used;
+
+ return strcmp(slice, suffix->buf) == 0;
}
void
-varbuf_end_str(struct varbuf *v)
+varbuf_trim_varbuf_prefix(struct varbuf *v, struct varbuf *prefix)
{
- varbuf_grow(v, 1);
- v->buf[v->used] = '\0';
+ if (!varbuf_has_prefix(v, prefix))
+ return;
+
+ memmove(v->buf, v->buf + prefix->used, v->used - prefix->used);
+ varbuf_trunc(v, v->used - prefix->used);
+}
+
+void
+varbuf_trim_char_prefix(struct varbuf *v, int prefix)
+{
+ const char *str = v->buf;
+ size_t len = v->used;
+
+ while (str[0] == prefix && len > 0) {
+ str++;
+ len--;
+ }
+ if (str != v->buf) {
+ memmove(v->buf, str, len);
+ varbuf_trunc(v, len);
+ }
}
int
@@ -239,10 +300,7 @@ varbuf_rollback_start(struct varbuf_state *vs)
if (vs->used)
internerr("varbuf buf(NULL) state_used(%zu) > 0",
vs->used);
- /* XXX: Ideally this would be handled by varbuf always having
- * a valid buf or switching all users to the getter, but for
- * now this will do. */
- return "";
+ return varbuf_str(vs->v);
}
return vs->v->buf + vs->used;
}
@@ -256,6 +314,9 @@ varbuf_detach(struct varbuf *v)
v->size = 0;
v->used = 0;
+ if (buf == NULL)
+ buf = m_strdup("");
+
return buf;
}