diff options
Diffstat (limited to 'lib/dpkg/varbuf.c')
-rw-r--r-- | lib/dpkg/varbuf.c | 93 |
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; } |