summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Nikias Bassen2023-02-03 16:48:34 +0100
committerGravatar Nikias Bassen2023-02-03 16:48:34 +0100
commit706771e357570d1bee268fc7c2233506da967bcd (patch)
tree4239e647149f94c5f6b5df998a88c8daf39a7b23
parentc2f396a53745a74dd58de3b55092a77e0e9f639d (diff)
downloadlibplist-706771e357570d1bee268fc7c2233506da967bcd.tar.gz
libplist-706771e357570d1bee268fc7c2233506da967bcd.tar.bz2
Add new plist_sort() function
-rw-r--r--include/plist/plist.h8
-rw-r--r--src/plist.c61
2 files changed, 69 insertions, 0 deletions
diff --git a/include/plist/plist.h b/include/plist/plist.h
index 2bb947f..0a21499 100644
--- a/include/plist/plist.h
+++ b/include/plist/plist.h
@@ -1072,6 +1072,14 @@ extern "C"
1072 int plist_data_val_contains(plist_t datanode, const uint8_t* cmpval, size_t n); 1072 int plist_data_val_contains(plist_t datanode, const uint8_t* cmpval, size_t n);
1073 1073
1074 /** 1074 /**
1075 * Sort all PLIST_DICT key/value pairs in a property list lexicographically
1076 * by key. Recurses into the child nodes if necessary.
1077 *
1078 * @param plist The property list to perform the sorting operation on.
1079 */
1080 void plist_sort(plist_t plist);
1081
1082 /**
1075 * Free memory allocated by relevant libplist API calls: 1083 * Free memory allocated by relevant libplist API calls:
1076 * - plist_to_xml() 1084 * - plist_to_xml()
1077 * - plist_to_bin() 1085 * - plist_to_bin()
diff --git a/src/plist.c b/src/plist.c
index b120046..72c3e98 100644
--- a/src/plist.c
+++ b/src/plist.c
@@ -1495,3 +1495,64 @@ PLIST_API int plist_data_val_contains(plist_t datanode, const uint8_t* cmpval, s
1495 plist_data_t data = plist_get_data(datanode); 1495 plist_data_t data = plist_get_data(datanode);
1496 return (memmem(data->buff, data->length, cmpval, n) != NULL); 1496 return (memmem(data->buff, data->length, cmpval, n) != NULL);
1497} 1497}
1498
1499PLIST_API void plist_sort(plist_t plist)
1500{
1501 if (!plist) {
1502 return;
1503 }
1504 if (PLIST_IS_ARRAY(plist)) {
1505 uint32_t n = plist_array_get_size(plist);
1506 uint32_t i = 0;
1507 for (i = 0; i < n; i++) {
1508 plist_sort(plist_array_get_item(plist, i));
1509 }
1510 } else if (PLIST_IS_DICT(plist)) {
1511 node_t *node = (node_t*)plist;
1512 node_t *ch;
1513 for (ch = node_first_child(node); ch; ch = node_next_sibling(ch)) {
1514 ch = node_next_sibling(ch);
1515 plist_sort((plist_t)ch);
1516 }
1517 #define KEY_DATA(x) (x->data)
1518 #define VAL_DATA(x) (x->next->data)
1519 #define VAL_COUNT(x) (x->next->count)
1520 #define VAL_CHDN(x) (x->next->children)
1521 #define NEXT_KEY(x) (x->next->next)
1522 #define NEXT_VAL(x) (NEXT_KEY(x)->next)
1523 #define NEXT_KEY_DATA(x) (NEXT_KEY(x)->data)
1524 #define NEXT_VAL_DATA(x) (NEXT_VAL(x)->data)
1525 #define NEXT_VAL_CHDN(x) (NEXT_VAL(x)->children)
1526 #define NEXT_VAL_COUNT(x) (NEXT_VAL(x)->count)
1527 #define KEY_STRVAL(x) ((plist_data_t)(KEY_DATA(x)))->strval
1528 #define NEXT_KEY_STRVAL(x) ((plist_data_t)(NEXT_KEY_DATA(x)))->strval
1529 int swapped = 0;
1530 do {
1531 swapped = 0;
1532 node_t *lptr = NULL;
1533 node_t *ptr_key = node_first_child((node_t*)plist);
1534 while (NEXT_KEY(ptr_key) != lptr) {
1535 if (strcmp(KEY_STRVAL(ptr_key), NEXT_KEY_STRVAL(ptr_key)) > 0) {
1536 // backup old values
1537 void* key_data_tmp = KEY_DATA(ptr_key);
1538 void* val_data_tmp = VAL_DATA(ptr_key);
1539 struct node_list_t *val_chdn_tmp = VAL_CHDN(ptr_key);
1540 unsigned int val_count_tmp = VAL_COUNT(ptr_key);
1541 // replace current with next
1542 KEY_DATA(ptr_key) = NEXT_KEY_DATA(ptr_key);
1543 VAL_DATA(ptr_key) = NEXT_VAL_DATA(ptr_key);
1544 VAL_CHDN(ptr_key) = NEXT_VAL_CHDN(ptr_key);
1545 VAL_COUNT(ptr_key) = NEXT_VAL_COUNT(ptr_key);
1546 // replace next with old
1547 NEXT_KEY_DATA(ptr_key) = key_data_tmp;
1548 NEXT_VAL_DATA(ptr_key) = val_data_tmp;
1549 NEXT_VAL_CHDN(ptr_key) = val_chdn_tmp;
1550 NEXT_VAL_COUNT(ptr_key) = val_count_tmp;
1551 swapped = 1;
1552 }
1553 ptr_key = NEXT_KEY(ptr_key);
1554 }
1555 lptr = ptr_key;
1556 } while (swapped);
1557 }
1558}