summaryrefslogtreecommitdiffstats
path: root/src/plist.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/plist.c')
-rw-r--r--src/plist.c80
1 files changed, 69 insertions, 11 deletions
diff --git a/src/plist.c b/src/plist.c
index 70386bc..f22a8a0 100644
--- a/src/plist.c
+++ b/src/plist.c
@@ -28,6 +28,7 @@
28#include <stdio.h> 28#include <stdio.h>
29#include <math.h> 29#include <math.h>
30#include <assert.h> 30#include <assert.h>
31#include <limits.h>
31 32
32#ifdef WIN32 33#ifdef WIN32
33#include <windows.h> 34#include <windows.h>
@@ -37,6 +38,7 @@
37 38
38#include <node.h> 39#include <node.h>
39#include <hashtable.h> 40#include <hashtable.h>
41#include <ptrarray.h>
40 42
41extern void plist_xml_init(void); 43extern void plist_xml_init(void);
42extern void plist_xml_deinit(void); 44extern void plist_xml_deinit(void);
@@ -190,6 +192,9 @@ void plist_free_data(plist_data_t data)
190 case PLIST_DATA: 192 case PLIST_DATA:
191 free(data->buff); 193 free(data->buff);
192 break; 194 break;
195 case PLIST_ARRAY:
196 ptr_array_free(data->hashtable);
197 break;
193 case PLIST_DICT: 198 case PLIST_DICT:
194 hash_table_destroy(data->hashtable); 199 hash_table_destroy(data->hashtable);
195 break; 200 break;
@@ -338,6 +343,20 @@ static void plist_copy_node(node_t *node, void *parent_node_ptr)
338 case PLIST_STRING: 343 case PLIST_STRING:
339 newdata->strval = strdup((char *) data->strval); 344 newdata->strval = strdup((char *) data->strval);
340 break; 345 break;
346 case PLIST_ARRAY:
347 if (data->hashtable) {
348 ptrarray_t* pa = ptr_array_new(((ptrarray_t*)data->hashtable)->capacity);
349 assert(pa);
350 plist_t current = NULL;
351 for (current = (plist_t)node_first_child(node);
352 pa && current;
353 current = (plist_t)node_next_sibling(current))
354 {
355 ptr_array_add(pa, current);
356 }
357 newdata->hashtable = pa;
358 }
359 break;
341 case PLIST_DICT: 360 case PLIST_DICT:
342 if (data->hashtable) { 361 if (data->hashtable) {
343 hashtable_t* ht = hash_table_new(dict_key_hash, dict_key_compare, NULL); 362 hashtable_t* ht = hash_table_new(dict_key_hash, dict_key_compare, NULL);
@@ -392,9 +411,14 @@ PLIST_API uint32_t plist_array_get_size(plist_t node)
392PLIST_API plist_t plist_array_get_item(plist_t node, uint32_t n) 411PLIST_API plist_t plist_array_get_item(plist_t node, uint32_t n)
393{ 412{
394 plist_t ret = NULL; 413 plist_t ret = NULL;
395 if (node && PLIST_ARRAY == plist_get_node_type(node)) 414 if (node && PLIST_ARRAY == plist_get_node_type(node) && n < INT_MAX)
396 { 415 {
397 ret = (plist_t)node_nth_child(node, n); 416 ptrarray_t *pa = ((plist_data_t)((node_t*)node)->data)->hashtable;
417 if (pa) {
418 ret = (plist_t)ptr_array_index(pa, n);
419 } else {
420 ret = (plist_t)node_nth_child(node, n);
421 }
398 } 422 }
399 return ret; 423 return ret;
400} 424}
@@ -409,19 +433,46 @@ PLIST_API uint32_t plist_array_get_item_index(plist_t node)
409 return 0; 433 return 0;
410} 434}
411 435
436static void _plist_array_post_insert(plist_t node, plist_t item, long n)
437{
438 ptrarray_t *pa = ((plist_data_t)((node_t*)node)->data)->hashtable;
439 if (pa) {
440 /* store pointer to item in array */
441 ptr_array_insert(pa, item, n);
442 } else {
443 if (((node_t*)node)->count > 100) {
444 /* make new lookup array */
445 pa = ptr_array_new(128);
446 plist_t current = NULL;
447 for (current = (plist_t)node_first_child(node);
448 pa && current;
449 current = (plist_t)node_next_sibling(current))
450 {
451 ptr_array_add(pa, current);
452 }
453 ((plist_data_t)((node_t*)node)->data)->hashtable = pa;
454 }
455 }
456}
457
412PLIST_API void plist_array_set_item(plist_t node, plist_t item, uint32_t n) 458PLIST_API void plist_array_set_item(plist_t node, plist_t item, uint32_t n)
413{ 459{
414 if (node && PLIST_ARRAY == plist_get_node_type(node)) 460 if (node && PLIST_ARRAY == plist_get_node_type(node) && n < INT_MAX)
415 { 461 {
416 plist_t old_item = plist_array_get_item(node, n); 462 plist_t old_item = plist_array_get_item(node, n);
417 if (old_item) 463 if (old_item)
418 { 464 {
419 int idx = plist_free_node(old_item); 465 int idx = plist_free_node(old_item);
420 if (idx < 0) { 466 assert(idx >= 0);
421 node_attach(node, item); 467 if (idx < 0) {
422 } else { 468 return;
423 node_insert(node, idx, item); 469 } else {
424 } 470 node_insert(node, idx, item);
471 ptrarray_t* pa = ((plist_data_t)((node_t*)node)->data)->hashtable;
472 if (pa) {
473 ptr_array_set(pa, item, idx);
474 }
475 }
425 } 476 }
426 } 477 }
427 return; 478 return;
@@ -432,26 +483,32 @@ PLIST_API void plist_array_append_item(plist_t node, plist_t item)
432 if (node && PLIST_ARRAY == plist_get_node_type(node)) 483 if (node && PLIST_ARRAY == plist_get_node_type(node))
433 { 484 {
434 node_attach(node, item); 485 node_attach(node, item);
486 _plist_array_post_insert(node, item, -1);
435 } 487 }
436 return; 488 return;
437} 489}
438 490
439PLIST_API void plist_array_insert_item(plist_t node, plist_t item, uint32_t n) 491PLIST_API void plist_array_insert_item(plist_t node, plist_t item, uint32_t n)
440{ 492{
441 if (node && PLIST_ARRAY == plist_get_node_type(node)) 493 if (node && PLIST_ARRAY == plist_get_node_type(node) && n < INT_MAX)
442 { 494 {
443 node_insert(node, n, item); 495 node_insert(node, n, item);
496 _plist_array_post_insert(node, item, (long)n);
444 } 497 }
445 return; 498 return;
446} 499}
447 500
448PLIST_API void plist_array_remove_item(plist_t node, uint32_t n) 501PLIST_API void plist_array_remove_item(plist_t node, uint32_t n)
449{ 502{
450 if (node && PLIST_ARRAY == plist_get_node_type(node)) 503 if (node && PLIST_ARRAY == plist_get_node_type(node) && n < INT_MAX)
451 { 504 {
452 plist_t old_item = plist_array_get_item(node, n); 505 plist_t old_item = plist_array_get_item(node, n);
453 if (old_item) 506 if (old_item)
454 { 507 {
508 ptrarray_t* pa = ((plist_data_t)((node_t*)node)->data)->hashtable;
509 if (pa) {
510 ptr_array_remove(pa, n);
511 }
455 plist_free(old_item); 512 plist_free(old_item);
456 } 513 }
457 } 514 }
@@ -586,8 +643,9 @@ PLIST_API void plist_dict_set_item(plist_t node, const char* key, plist_t item)
586 plist_t key_node = NULL; 643 plist_t key_node = NULL;
587 if (old_item) { 644 if (old_item) {
588 int idx = plist_free_node(old_item); 645 int idx = plist_free_node(old_item);
646 assert(idx >= 0);
589 if (idx < 0) { 647 if (idx < 0) {
590 node_attach(node, item); 648 return;
591 } else { 649 } else {
592 node_insert(node, idx, item); 650 node_insert(node, idx, item);
593 } 651 }