Code

Merged branch 'master' of git://git.tokkee.org/sysdb.
[sysdb.git] / src / utils / strbuf.c
index 2b64480c55fc5960c816f83ef3a6b3bf626c1faf..ee419b7ea20994efaeeaac3d6ae1d246c402dcb0 100644 (file)
@@ -119,9 +119,14 @@ sdb_strbuf_vappend(sdb_strbuf_t *strbuf, const char *fmt, va_list ap)
 
        assert((strbuf->size == 0) || (strbuf->string[strbuf->pos] == '\0'));
 
-       if (strbuf->pos >= strbuf->size)
+       if (! strbuf->size) {
                /* use some arbitrary but somewhat reasonable default */
-               if (strbuf_resize(strbuf, strbuf->size ? 2 * strbuf->size : 64))
+               if (strbuf_resize(strbuf, 64))
+                       return -1;
+       }
+       /* make sure to reserve space for the nul-byte */
+       else if (strbuf->pos >= strbuf->size - 1)
+               if (strbuf_resize(strbuf, 2 * strbuf->size))
                        return -1;
 
        assert(strbuf->size && strbuf->string);
@@ -137,8 +142,12 @@ sdb_strbuf_vappend(sdb_strbuf_t *strbuf, const char *fmt, va_list ap)
                return status;
        }
 
-       if ((size_t)status >= strbuf->size - strbuf->pos) {
-               strbuf_resize(strbuf, (size_t)status + 1);
+       /* 'status' does not include nul-byte */
+       if ((size_t)status >= strbuf->size - strbuf->pos - 1) {
+               if (strbuf_resize(strbuf, strbuf->size + (size_t)status)) {
+                       va_end(aq);
+                       return -1;
+               }
 
                /* reset string and try again */
                strbuf->string[strbuf->pos] = '\0';
@@ -238,13 +247,18 @@ sdb_strbuf_memcpy(sdb_strbuf_t *strbuf, const void *data, size_t n)
 ssize_t
 sdb_strbuf_read(sdb_strbuf_t *strbuf, int fd, size_t n)
 {
+       ssize_t ret;
+
        if (! strbuf)
                return -1;
 
        if (strbuf_resize(strbuf, strbuf->pos + n + 1))
                return -1;
 
-       return read(fd, strbuf->string + strbuf->pos, n);
+       ret = read(fd, strbuf->string + strbuf->pos, n);
+       if (ret > 0)
+               strbuf->pos += (size_t)ret;
+       return ret;
 } /* sdb_strbuf_read */
 
 ssize_t
@@ -269,23 +283,44 @@ sdb_strbuf_chomp(sdb_strbuf_t *strbuf)
 } /* sdb_strbuf_chomp */
 
 void
-sdb_strbuf_skip(sdb_strbuf_t *strbuf, size_t n)
+sdb_strbuf_skip(sdb_strbuf_t *strbuf, size_t offset, size_t n)
 {
+       char *start;
+       size_t len;
+
        if ((! strbuf) || (! n))
                return;
 
-       if (n >= strbuf->pos) {
-               strbuf->string[0] = '\0';
-               strbuf->pos = 0;
+       if (offset >= strbuf->pos)
+               return;
+
+       len = strbuf->pos - offset;
+
+       if (n >= len) {
+               strbuf->string[offset] = '\0';
+               strbuf->pos = offset;
                return;
        }
 
-       assert(n < strbuf->pos);
-       memmove(strbuf->string, strbuf->string + n, strbuf->pos - n);
+       assert(offset + n < strbuf->pos);
+       assert(offset < strbuf->pos);
+
+       start = strbuf->string + offset;
+       memmove(start, start + n, strbuf->pos - n);
        strbuf->pos -= n;
        strbuf->string[strbuf->pos] = '\0';
 } /* sdb_strbuf_skip */
 
+void
+sdb_strbuf_clear(sdb_strbuf_t *strbuf)
+{
+       if ((! strbuf) || (! strbuf->size))
+               return;
+
+       strbuf->string[0] = '\0';
+       strbuf->pos = 0;
+} /* sdb_strbuf_clear */
+
 const char *
 sdb_strbuf_string(sdb_strbuf_t *strbuf)
 {