summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorGravatar Nikias Bassen2018-12-10 01:40:56 +0100
committerGravatar Nikias Bassen2018-12-10 01:40:56 +0100
commit71dd25e14616bd261c3b6c80ff990cd1078266f6 (patch)
tree1d95c664a9bd18eb49604fb92fe0e0be3fa0969e /src
parentaf994607c799f3bfcbab280ef97e3bd85fe69ed2 (diff)
downloadlibplist-71dd25e14616bd261c3b6c80ff990cd1078266f6.tar.gz
libplist-71dd25e14616bd261c3b6c80ff990cd1078266f6.tar.bz2
bplist: Improve performance and memory usage when writing binary plist
Diffstat (limited to 'src')
-rw-r--r--src/bplist.c86
-rw-r--r--src/bytearray.c4
-rw-r--r--src/bytearray.h2
-rw-r--r--src/strbuf.h2
4 files changed, 88 insertions, 6 deletions
diff --git a/src/bplist.c b/src/bplist.c
index c4fe3df..69f3dca 100644
--- a/src/bplist.c
+++ b/src/bplist.c
@@ -1184,7 +1184,7 @@ PLIST_API void plist_to_bin(plist_t plist, char **plist_bin, uint32_t * length)
1184 return; 1184 return;
1185 1185
1186 //list of objects 1186 //list of objects
1187 objects = ptr_array_new(256); 1187 objects = ptr_array_new(4096);
1188 //hashtable to write only once same nodes 1188 //hashtable to write only once same nodes
1189 ref_table = hash_table_new(plist_data_hash, plist_data_compare, free); 1189 ref_table = hash_table_new(plist_data_hash, plist_data_compare, free);
1190 1190
@@ -1201,8 +1201,90 @@ PLIST_API void plist_to_bin(plist_t plist, char **plist_bin, uint32_t * length)
1201 root_object = 0; //root is first in list 1201 root_object = 0; //root is first in list
1202 offset_table_index = 0; //unknown yet 1202 offset_table_index = 0; //unknown yet
1203 1203
1204 //figure out the storage size required
1205 size_t req = 0;
1206 for (i = 0; i < num_objects; i++)
1207 {
1208 node_t* node = ptr_array_index(objects, i);
1209 plist_data_t data = plist_get_data(node);
1210 uint64_t size;
1211 uint8_t bsize;
1212 switch (data->type)
1213 {
1214 case PLIST_BOOLEAN:
1215 req += 1;
1216 break;
1217 case PLIST_KEY:
1218 case PLIST_STRING:
1219 req += 1;
1220 if (data->length >= 15) {
1221 bsize = get_needed_bytes(data->length);
1222 if (bsize == 3) bsize = 4;
1223 req += 1;
1224 req += bsize;
1225 }
1226 if ( is_ascii_string(data->strval, data->length) )
1227 {
1228 req += data->length;
1229 }
1230 else
1231 {
1232 req += data->length * 2;
1233 }
1234 break;
1235 case PLIST_REAL:
1236 size = get_real_bytes(data->realval);
1237 req += 1;
1238 req += size;
1239 break;
1240 case PLIST_DATE:
1241 req += 9;
1242 break;
1243 case PLIST_ARRAY:
1244 size = node_n_children(node);
1245 req += 1;
1246 if (size >= 15) {
1247 bsize = get_needed_bytes(size);
1248 if (bsize == 3) bsize = 4;
1249 req += 1;
1250 req += bsize;
1251 }
1252 req += size * ref_size;
1253 break;
1254 case PLIST_DICT:
1255 size = node_n_children(node) / 2;
1256 req += 1;
1257 if (size >= 15) {
1258 bsize = get_needed_bytes(size);
1259 if (bsize == 3) bsize = 4;
1260 req += 1;
1261 req += bsize;
1262 }
1263 req += size * 2 * ref_size;
1264 break;
1265 default:
1266 size = data->length;
1267 req += 1;
1268 if (size >= 15) {
1269 bsize = get_needed_bytes(size);
1270 if (bsize == 3) bsize = 4;
1271 req += 1;
1272 req += bsize;
1273 }
1274 req += data->length;
1275 break;
1276 }
1277 }
1278 // add size of magic
1279 req += BPLIST_MAGIC_SIZE;
1280 req += BPLIST_VERSION_SIZE;
1281 // add size of offset table
1282 req += get_needed_bytes(req) * num_objects;
1283 // add size of trailer
1284 req += sizeof(bplist_trailer_t);
1285
1204 //setup a dynamic bytes array to store bplist in 1286 //setup a dynamic bytes array to store bplist in
1205 bplist_buff = byte_array_new(); 1287 bplist_buff = byte_array_new(req);
1206 1288
1207 //set magic number and version 1289 //set magic number and version
1208 byte_array_append(bplist_buff, BPLIST_MAGIC, BPLIST_MAGIC_SIZE); 1290 byte_array_append(bplist_buff, BPLIST_MAGIC, BPLIST_MAGIC_SIZE);
diff --git a/src/bytearray.c b/src/bytearray.c
index fff5089..7d0549b 100644
--- a/src/bytearray.c
+++ b/src/bytearray.c
@@ -23,10 +23,10 @@
23 23
24#define PAGE_SIZE 4096 24#define PAGE_SIZE 4096
25 25
26bytearray_t *byte_array_new() 26bytearray_t *byte_array_new(size_t initial)
27{ 27{
28 bytearray_t *a = (bytearray_t*)malloc(sizeof(bytearray_t)); 28 bytearray_t *a = (bytearray_t*)malloc(sizeof(bytearray_t));
29 a->capacity = PAGE_SIZE * 8; 29 a->capacity = (initial > PAGE_SIZE) ? (initial+(PAGE_SIZE-1)) & (~(PAGE_SIZE-1)) : PAGE_SIZE;
30 a->data = malloc(a->capacity); 30 a->data = malloc(a->capacity);
31 a->len = 0; 31 a->len = 0;
32 return a; 32 return a;
diff --git a/src/bytearray.h b/src/bytearray.h
index aae8c31..312e2aa 100644
--- a/src/bytearray.h
+++ b/src/bytearray.h
@@ -28,7 +28,7 @@ typedef struct bytearray_t {
28 size_t capacity; 28 size_t capacity;
29} bytearray_t; 29} bytearray_t;
30 30
31bytearray_t *byte_array_new(); 31bytearray_t *byte_array_new(size_t initial);
32void byte_array_free(bytearray_t *ba); 32void byte_array_free(bytearray_t *ba);
33void byte_array_grow(bytearray_t *ba, size_t amount); 33void byte_array_grow(bytearray_t *ba, size_t amount);
34void byte_array_append(bytearray_t *ba, void *buf, size_t len); 34void byte_array_append(bytearray_t *ba, void *buf, size_t len);
diff --git a/src/strbuf.h b/src/strbuf.h
index ba2c909..b805892 100644
--- a/src/strbuf.h
+++ b/src/strbuf.h
@@ -26,7 +26,7 @@
26 26
27typedef struct bytearray_t strbuf_t; 27typedef struct bytearray_t strbuf_t;
28 28
29#define str_buf_new() byte_array_new() 29#define str_buf_new() byte_array_new(32768)
30#define str_buf_free(__ba) byte_array_free(__ba) 30#define str_buf_free(__ba) byte_array_free(__ba)
31#define str_buf_grow(__ba, __am) byte_array_grow(__ba, __am) 31#define str_buf_grow(__ba, __am) byte_array_grow(__ba, __am)
32#define str_buf_append(__ba, __str, __len) byte_array_append(__ba, (void*)(__str), __len) 32#define str_buf_append(__ba, __str, __len) byte_array_append(__ba, (void*)(__str), __len)