summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: f540b1d)
raw | patch | inline | side by side (parent: f540b1d)
author | Sebastian Harl <sh@tokkee.org> | |
Mon, 12 May 2014 11:29:29 +0000 (13:29 +0200) | ||
committer | Sebastian Harl <sh@tokkee.org> | |
Mon, 12 May 2014 11:29:29 +0000 (13:29 +0200) |
While this might generate some churn in some situations, care has been taken
to avoid this as much as possible while providing a (hopefully) good balance
between memory usage and the need to reallocate memory.
to avoid this as much as possible while providing a (hopefully) good balance
between memory usage and the need to reallocate memory.
src/utils/strbuf.c | patch | blob | history |
diff --git a/src/utils/strbuf.c b/src/utils/strbuf.c
index 822f01928c4437b40bb4d621f905cf0b649cea6a..6c881be18e4975517f4c5080747e5d6f83a183f1 100644 (file)
--- a/src/utils/strbuf.c
+++ b/src/utils/strbuf.c
#include <unistd.h>
+/* free memory if most of the buffer is unused */
+#define CHECK_SHRINK(strbuf) \
+ do { \
+ if ((strbuf)->pos < (strbuf)->size / 3) \
+ /* don't free all memory to avoid churn */ \
+ strbuf_resize((strbuf), 2 * (strbuf)->pos); \
+ } while (0)
+
/*
* private data structures
*/
{
char *tmp;
- if (new_size <= strbuf->size)
- return 0;
+ if (new_size <= strbuf->pos)
+ return -1;
tmp = realloc(strbuf->string, new_size);
if (! tmp)
return -1;
- strbuf->string = tmp;
+ if (new_size)
+ strbuf->string = tmp;
+ else
+ strbuf->string = NULL;
strbuf->size = new_size;
return 0;
} /* strbuf_resize */
/* 'status' does not include nul-byte */
if ((size_t)status >= strbuf->size - strbuf->pos - 1) {
- if (strbuf_resize(strbuf, strbuf->size + (size_t)status)) {
+ if (strbuf_resize(strbuf, strbuf->size + (size_t)status + 1)) {
va_end(aq);
return -1;
}
strbuf->pos += (size_t)status;
va_end(aq);
+
+ /* even though this function always appends to the existing buffer, the
+ * size might have previously been reset */
+ CHECK_SHRINK(strbuf);
+
return (ssize_t)status;
} /* sdb_strbuf_vappend */
strbuf->pos += n;
strbuf->string[strbuf->pos] = '\0';
+ /* even though this function always appends to the existing buffer, the
+ * size might have previously been reset */
+ CHECK_SHRINK(strbuf);
+
return (ssize_t)n;
} /* sdb_strbuf_memappend */
if (! strbuf)
return -1;
- if (strbuf_resize(strbuf, strbuf->pos + n + 1))
- return -1;
+ if (strbuf->pos + n + 1 >= strbuf->size)
+ if (strbuf_resize(strbuf, strbuf->pos + n + 1))
+ return -1;
ret = read(fd, strbuf->string + strbuf->pos, n);
if (ret > 0)
memmove(start, start + n, len - n);
strbuf->pos -= n;
strbuf->string[strbuf->pos] = '\0';
+
+ /* don't resize now but wait for the next write to avoid churn */
} /* sdb_strbuf_skip */
void
strbuf->string[0] = '\0';
strbuf->pos = 0;
+
+ /* don't resize now but wait for the next write to avoid churn */
} /* sdb_strbuf_clear */
const char *