Commit 71dd25e1 authored by Nikias Bassen's avatar Nikias Bassen

bplist: Improve performance and memory usage when writing binary plist

parent af994607
......@@ -1184,7 +1184,7 @@ PLIST_API void plist_to_bin(plist_t plist, char **plist_bin, uint32_t * length)
return;
//list of objects
objects = ptr_array_new(256);
objects = ptr_array_new(4096);
//hashtable to write only once same nodes
ref_table = hash_table_new(plist_data_hash, plist_data_compare, free);
......@@ -1201,8 +1201,90 @@ PLIST_API void plist_to_bin(plist_t plist, char **plist_bin, uint32_t * length)
root_object = 0; //root is first in list
offset_table_index = 0; //unknown yet
//figure out the storage size required
size_t req = 0;
for (i = 0; i < num_objects; i++)
{
node_t* node = ptr_array_index(objects, i);
plist_data_t data = plist_get_data(node);
uint64_t size;
uint8_t bsize;
switch (data->type)
{
case PLIST_BOOLEAN:
req += 1;
break;
case PLIST_KEY:
case PLIST_STRING:
req += 1;
if (data->length >= 15) {
bsize = get_needed_bytes(data->length);
if (bsize == 3) bsize = 4;
req += 1;
req += bsize;
}
if ( is_ascii_string(data->strval, data->length) )
{
req += data->length;
}
else
{
req += data->length * 2;
}
break;
case PLIST_REAL:
size = get_real_bytes(data->realval);
req += 1;
req += size;
break;
case PLIST_DATE:
req += 9;
break;
case PLIST_ARRAY:
size = node_n_children(node);
req += 1;
if (size >= 15) {
bsize = get_needed_bytes(size);
if (bsize == 3) bsize = 4;
req += 1;
req += bsize;
}
req += size * ref_size;
break;
case PLIST_DICT:
size = node_n_children(node) / 2;
req += 1;
if (size >= 15) {
bsize = get_needed_bytes(size);
if (bsize == 3) bsize = 4;
req += 1;
req += bsize;
}
req += size * 2 * ref_size;
break;
default:
size = data->length;
req += 1;
if (size >= 15) {
bsize = get_needed_bytes(size);
if (bsize == 3) bsize = 4;
req += 1;
req += bsize;
}
req += data->length;
break;
}
}
// add size of magic
req += BPLIST_MAGIC_SIZE;
req += BPLIST_VERSION_SIZE;
// add size of offset table
req += get_needed_bytes(req) * num_objects;
// add size of trailer
req += sizeof(bplist_trailer_t);
//setup a dynamic bytes array to store bplist in
bplist_buff = byte_array_new();
bplist_buff = byte_array_new(req);
//set magic number and version
byte_array_append(bplist_buff, BPLIST_MAGIC, BPLIST_MAGIC_SIZE);
......
......@@ -23,10 +23,10 @@
#define PAGE_SIZE 4096
bytearray_t *byte_array_new()
bytearray_t *byte_array_new(size_t initial)
{
bytearray_t *a = (bytearray_t*)malloc(sizeof(bytearray_t));
a->capacity = PAGE_SIZE * 8;
a->capacity = (initial > PAGE_SIZE) ? (initial+(PAGE_SIZE-1)) & (~(PAGE_SIZE-1)) : PAGE_SIZE;
a->data = malloc(a->capacity);
a->len = 0;
return a;
......
......@@ -28,7 +28,7 @@ typedef struct bytearray_t {
size_t capacity;
} bytearray_t;
bytearray_t *byte_array_new();
bytearray_t *byte_array_new(size_t initial);
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);
......
......@@ -26,7 +26,7 @@
typedef struct bytearray_t strbuf_t;
#define str_buf_new() byte_array_new()
#define str_buf_new() byte_array_new(32768)
#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)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment