libimobiledevice / libplist

A library to handle Apple Property List format in binary or XML
https://libimobiledevice.org
GNU Lesser General Public License v2.1
535 stars 304 forks source link

It is recommended to add a function of plist_rename_key #127

Closed xdeng closed 5 years ago

xdeng commented 5 years ago

In some places you need to change the key。

nikias commented 5 years ago

Can you give an example? Apple's CFDictionary API does not offer this feature so I don't see a reason to add it. Also it can be done with removing an item from a dictionary and adding it with a different key.

xdeng commented 5 years ago

20181116170630

This file size 15M plist_from_xml() memory usage 200M

void modify_plist(plist_t oplist, plist_t *nplist)
{   
    *nplist = plist_new_dict();
    plist_dict_iter iter = NULL;
    plist_dict_new_iter(oplist, &iter);
    if (iter) {
        char *key = NULL;
        plist_t node = NULL;

        plist_dict_next_item(oplist, iter, &key, &node);
        while (node) {
            char *tp = generate_id();

            plist_dict_set_item(*nplist, tp, plist_copy(node));

            free(tp);
            free(key);
            plist_dict_next_item(oplist, iter, &key, &node);
        }
        free(iter);
    }
}

two plist_t node memory usage 400M

xdeng commented 5 years ago

and also libplist memory usage is high and read slow (libxml2 ver) tinyxml2 read xml memory usage 70M pugixml read xml memory usage 50M

xdeng commented 5 years ago

Maybe not the problem of adding functions, but the problem of optimizing the library.

nikias commented 5 years ago

I added a lot of optimizations that will reduce the memory usage. Please have a look: ac3be565c413f6964f0188e1c608c1bf8848db29

xdeng commented 5 years ago

@nikias I tested the libxml version before. I have not tested the new version. If I have time, I will test it.

xdeng commented 5 years ago

@nikias The memory usage is high because the leaf nodes have more data that is not used.

nikias commented 5 years ago

I added a new function plist_dict_item_get_key() that returns the key node for a given PLIST_DICT item. Example:

plist_t n = plist_dict_get_item(dict, "yeah");
plist_t key = plist_dict_item_get_key(n);
plist_set_key_val(key, "nope");

or in a classical iterator loop:

plist_t node = NULL;
do {
    node = NULL;
    char *key = NULL;
    plist_dict_next_item(dict, iter, &key, &node);
    if (key) {
        plist_t key_node = plist_dict_item_get_key(node);
        // decide wether to rename the key or not
        plist_set_key_val(key_node, "newkey");
        free(key);
    }
} while (node);

See commit ea37ed01b8c7e05078620ed039899ddff48eac1c.