summaryrefslogtreecommitdiffstats
path: root/src/bplist.c
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/bplist.c
parentaf994607c799f3bfcbab280ef97e3bd85fe69ed2 (diff)
downloadlibplist-71dd25e14616bd261c3b6c80ff990cd1078266f6.tar.gz
libplist-71dd25e14616bd261c3b6c80ff990cd1078266f6.tar.bz2
bplist: Improve performance and memory usage when writing binary plist
Diffstat (limited to 'src/bplist.c')
-rw-r--r--src/bplist.c86
1 files changed, 84 insertions, 2 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);