diff options
author | Nikias Bassen | 2017-02-15 15:14:12 +0100 |
---|---|---|
committer | Nikias Bassen | 2017-02-15 15:14:12 +0100 |
commit | 8ad21e6b59e5e5a3104660f17ad2b0e9122edecf (patch) | |
tree | 0d39423c866b90854618c28eb7a8f312374bdb4e | |
parent | 32ee5213fe64f1e10ec76c1ee861ee6f233120dd (diff) | |
download | libplist-8ad21e6b59e5e5a3104660f17ad2b0e9122edecf.tar.gz libplist-8ad21e6b59e5e5a3104660f17ad2b0e9122edecf.tar.bz2 |
xplist: Improve writing of large PLIST_DATA nodes by growing buffer in advance
Instead of letting the buffer grow by just the amount of bytes currently
transformed to base64 - which is basically line by line - we now calculate
the size of the output blob in advance and grow the buffer accordingly.
This will reduce the amount of reallocs to just one, which is especially
important for large data blobs.
While this is a general improvement for all platforms, it is on platforms
like Windows where realloc() can be REALLY slow; converting a 20mb blob to
XML can easily take up to a minute (due to the several hundred thousand
calls to realloc()). With this commit, it will be fast again.
-rw-r--r-- | src/bytearray.c | 11 | ||||
-rw-r--r-- | src/bytearray.h | 1 | ||||
-rw-r--r-- | src/strbuf.h | 1 | ||||
-rw-r--r-- | src/xplist.c | 1 |
4 files changed, 11 insertions, 3 deletions
diff --git a/src/bytearray.c b/src/bytearray.c index 861890e..fff5089 100644 --- a/src/bytearray.c +++ b/src/bytearray.c @@ -41,15 +41,20 @@ void byte_array_free(bytearray_t *ba) free(ba); } +void byte_array_grow(bytearray_t *ba, size_t amount) +{ + size_t increase = (amount > PAGE_SIZE) ? (amount+(PAGE_SIZE-1)) & (~(PAGE_SIZE-1)) : PAGE_SIZE; + ba->data = realloc(ba->data, ba->capacity + increase); + ba->capacity += increase; +} + void byte_array_append(bytearray_t *ba, void *buf, size_t len) { if (!ba || !ba->data || (len <= 0)) return; size_t remaining = ba->capacity-ba->len; if (len > remaining) { size_t needed = len - remaining; - size_t increase = (needed > PAGE_SIZE) ? (needed+(PAGE_SIZE-1)) & (~(PAGE_SIZE-1)) : PAGE_SIZE; - ba->data = realloc(ba->data, ba->capacity + increase); - ba->capacity += increase; + byte_array_grow(ba, needed); } memcpy(((char*)ba->data) + ba->len, buf, len); ba->len += len; diff --git a/src/bytearray.h b/src/bytearray.h index 1613143..aae8c31 100644 --- a/src/bytearray.h +++ b/src/bytearray.h @@ -30,6 +30,7 @@ typedef struct bytearray_t { bytearray_t *byte_array_new(); void byte_array_free(bytearray_t *ba); +void byte_array_grow(bytearray_t *ba, size_t amount); void byte_array_append(bytearray_t *ba, void *buf, size_t len); #endif diff --git a/src/strbuf.h b/src/strbuf.h index 6b7f9d3..ba2c909 100644 --- a/src/strbuf.h +++ b/src/strbuf.h @@ -28,6 +28,7 @@ typedef struct bytearray_t strbuf_t; #define str_buf_new() byte_array_new() #define str_buf_free(__ba) byte_array_free(__ba) +#define str_buf_grow(__ba, __am) byte_array_grow(__ba, __am) #define str_buf_append(__ba, __str, __len) byte_array_append(__ba, (void*)(__str), __len) #endif diff --git a/src/xplist.c b/src/xplist.c index 0e9b007..7f20ef2 100644 --- a/src/xplist.c +++ b/src/xplist.c @@ -294,6 +294,7 @@ static void node_to_xml(node_t* node, bytearray_t **outbuf, uint32_t depth) uint32_t maxread = ((76 - indent*8) / 4) * 3; size_t count = 0; size_t b64count = 0; + str_buf_grow(*outbuf, (node_data->length / 3 * 4) + 4 + (((node_data->length / maxread) + 1) * (indent+1))); while (j < node_data->length) { for (i = 0; i < indent; i++) { str_buf_append(*outbuf, "\t", 1); |