diff options
| author | 2018-12-10 01:40:56 +0100 | |
|---|---|---|
| committer | 2018-12-10 01:40:56 +0100 | |
| commit | 71dd25e14616bd261c3b6c80ff990cd1078266f6 (patch) | |
| tree | 1d95c664a9bd18eb49604fb92fe0e0be3fa0969e | |
| parent | af994607c799f3bfcbab280ef97e3bd85fe69ed2 (diff) | |
| download | libplist-71dd25e14616bd261c3b6c80ff990cd1078266f6.tar.gz libplist-71dd25e14616bd261c3b6c80ff990cd1078266f6.tar.bz2 | |
bplist: Improve performance and memory usage when writing binary plist
| -rw-r--r-- | src/bplist.c | 86 | ||||
| -rw-r--r-- | src/bytearray.c | 4 | ||||
| -rw-r--r-- | src/bytearray.h | 2 | ||||
| -rw-r--r-- | src/strbuf.h | 2 |
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 | ||
| 26 | bytearray_t *byte_array_new() | 26 | bytearray_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 | ||
| 31 | bytearray_t *byte_array_new(); | 31 | bytearray_t *byte_array_new(size_t initial); |
| 32 | void byte_array_free(bytearray_t *ba); | 32 | void byte_array_free(bytearray_t *ba); |
| 33 | void byte_array_grow(bytearray_t *ba, size_t amount); | 33 | void byte_array_grow(bytearray_t *ba, size_t amount); |
| 34 | void byte_array_append(bytearray_t *ba, void *buf, size_t len); | 34 | void 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 | ||
| 27 | typedef struct bytearray_t strbuf_t; | 27 | typedef 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) |
