diff options
| -rw-r--r-- | include/plist/plist.h | 47 | ||||
| -rw-r--r-- | src/plist.c | 81 |
2 files changed, 94 insertions, 34 deletions
diff --git a/include/plist/plist.h b/include/plist/plist.h index e12d6fa..699a0d6 100644 --- a/include/plist/plist.h +++ b/include/plist/plist.h | |||
| @@ -48,6 +48,7 @@ extern "C" { | |||
| 48 | #endif | 48 | #endif |
| 49 | 49 | ||
| 50 | #include <sys/types.h> | 50 | #include <sys/types.h> |
| 51 | #include <stdarg.h> | ||
| 51 | 52 | ||
| 52 | /** | 53 | /** |
| 53 | * \mainpage libplist : A library to handle Apple Property Lists | 54 | * \mainpage libplist : A library to handle Apple Property Lists |
| @@ -544,22 +545,25 @@ extern "C" { | |||
| 544 | ********************************************/ | 545 | ********************************************/ |
| 545 | 546 | ||
| 546 | /** | 547 | /** |
| 547 | * Find the first encountered #PLIST_KEY node mathing that key. | 548 | * Get a node from its path. Each path element depends on the associated father node type. |
| 549 | * For Dictionaries, var args are casted to const char*, for arrays, var args are caster to uint32_t | ||
| 548 | * Search is breath first order. | 550 | * Search is breath first order. |
| 549 | * | 551 | * |
| 550 | * @param plist the root node of the plist structure. | 552 | * @param plist the node to access result from. |
| 551 | * @param value the ASCII Key to match. | 553 | * @param length length of the path to access |
| 554 | * @return the value to access. | ||
| 552 | */ | 555 | */ |
| 553 | PLIST_API plist_t plist_find_node_by_key(plist_t plist, const char *value); | 556 | PLIST_API plist_t plist_access_path(plist_t plist, uint32_t length, ...); |
| 554 | 557 | ||
| 555 | /** | 558 | /** |
| 556 | * Find the first encountered #PLIST_STRING node mathing that string. | 559 | * Variadic version of #plist_access_path. |
| 557 | * Search is breath first order. | ||
| 558 | * | 560 | * |
| 559 | * @param plist the root node of the plist structure. | 561 | * @param plist the node to access result from. |
| 560 | * @param value the ASCII String to match. | 562 | * @param length length of the path to access |
| 563 | * @param v list of array's index and dic'st key | ||
| 564 | * @return the value to access. | ||
| 561 | */ | 565 | */ |
| 562 | PLIST_API plist_t plist_find_node_by_string(plist_t plist, const char *value); | 566 | PLIST_API plist_t plist_access_pathv(plist_t plist, uint32_t length, va_list v); |
| 563 | 567 | ||
| 564 | /** | 568 | /** |
| 565 | * Compare two node values | 569 | * Compare two node values |
| @@ -706,6 +710,31 @@ extern "C" { | |||
| 706 | */ | 710 | */ |
| 707 | PLIST_API void plist_add_sub_date_el(plist_t node, int32_t sec, int32_t usec); | 711 | PLIST_API void plist_add_sub_date_el(plist_t node, int32_t sec, int32_t usec); |
| 708 | 712 | ||
| 713 | |||
| 714 | /******************************************** | ||
| 715 | * * | ||
| 716 | * Utils * | ||
| 717 | * * | ||
| 718 | ********************************************/ | ||
| 719 | |||
| 720 | /** | ||
| 721 | * Find the first encountered #PLIST_KEY node mathing that key. | ||
| 722 | * Search is breath first order. | ||
| 723 | * | ||
| 724 | * @param plist the root node of the plist structure. | ||
| 725 | * @param value the ASCII Key to match. | ||
| 726 | */ | ||
| 727 | PLIST_API plist_t plist_find_node_by_key(plist_t plist, const char *value); | ||
| 728 | |||
| 729 | /** | ||
| 730 | * Find the first encountered #PLIST_STRING node mathing that string. | ||
| 731 | * Search is breath first order. | ||
| 732 | * | ||
| 733 | * @param plist the root node of the plist structure. | ||
| 734 | * @param value the ASCII String to match. | ||
| 735 | */ | ||
| 736 | PLIST_API plist_t plist_find_node_by_string(plist_t plist, const char *value); | ||
| 737 | |||
| 709 | /*@}*/ | 738 | /*@}*/ |
| 710 | 739 | ||
| 711 | 740 | ||
diff --git a/src/plist.c b/src/plist.c index 78ac07c..ed73d53 100644 --- a/src/plist.c +++ b/src/plist.c | |||
| @@ -408,37 +408,36 @@ static char compare_node_value(plist_type type, plist_data_t data, const void *v | |||
| 408 | return res; | 408 | return res; |
| 409 | } | 409 | } |
| 410 | 410 | ||
| 411 | static plist_t plist_find_node(plist_t plist, plist_type type, const void *value, uint64_t length) | 411 | plist_t plist_access_pathv(plist_t plist, uint32_t length, va_list v) |
| 412 | { | 412 | { |
| 413 | plist_t current = NULL; | 413 | plist_t current = plist; |
| 414 | 414 | plist_type type = PLIST_NONE; | |
| 415 | if (!plist) | 415 | uint32_t i = 0; |
| 416 | return NULL; | 416 | |
| 417 | 417 | for (i = 0; i < length && current; i++) { | |
| 418 | for (current = (plist_t)g_node_first_child(plist); current; current = (plist_t)g_node_next_sibling(current)) { | 418 | type = plist_get_node_type(current); |
| 419 | 419 | ||
| 420 | plist_data_t data = plist_get_data(current); | 420 | if (type == PLIST_ARRAY) { |
| 421 | 421 | uint32_t index = va_arg(v, uint32_t); | |
| 422 | if (data->type == type && data->length == length && compare_node_value(type, data, value, length)) { | 422 | current = plist_array_get_item(current, index); |
| 423 | return current; | ||
| 424 | } | 423 | } |
| 425 | if (data->type == PLIST_DICT || data->type == PLIST_ARRAY) { | 424 | else if (type == PLIST_DICT) { |
| 426 | plist_t sub = plist_find_node(current, type, value, length); | 425 | const char* key = va_arg(v, const char*); |
| 427 | if (sub) | 426 | current = plist_dict_get_item(current, key); |
| 428 | return sub; | ||
| 429 | } | 427 | } |
| 430 | } | 428 | } |
| 431 | return NULL; | 429 | return current; |
| 432 | } | 430 | } |
| 433 | 431 | ||
| 434 | plist_t plist_find_node_by_key(plist_t plist, const char *value) | 432 | plist_t plist_access_path(plist_t plist, uint32_t length, ...) |
| 435 | { | 433 | { |
| 436 | return plist_find_node(plist, PLIST_KEY, value, strlen(value)); | 434 | plist_t ret = NULL; |
| 437 | } | 435 | va_list v; |
| 438 | 436 | ||
| 439 | plist_t plist_find_node_by_string(plist_t plist, const char *value) | 437 | va_start(v, length); |
| 440 | { | 438 | ret = plist_access_pathv(plist, length, v); |
| 441 | return plist_find_node(plist, PLIST_STRING, value, strlen(value)); | 439 | va_end(v); |
| 440 | return ret; | ||
| 442 | } | 441 | } |
| 443 | 442 | ||
| 444 | static void plist_get_type_and_value(plist_t node, plist_type * type, void *value, uint64_t * length) | 443 | static void plist_get_type_and_value(plist_t node, plist_type * type, void *value, uint64_t * length) |
| @@ -886,4 +885,36 @@ void plist_add_sub_date_el(plist_t node, int32_t sec, int32_t usec) | |||
| 886 | plist_add_sub_element(node, PLIST_DATE, &val, sizeof(GTimeVal)); | 885 | plist_add_sub_element(node, PLIST_DATE, &val, sizeof(GTimeVal)); |
| 887 | } | 886 | } |
| 888 | 887 | ||
| 888 | static plist_t plist_find_node(plist_t plist, plist_type type, const void *value, uint64_t length) | ||
| 889 | { | ||
| 890 | plist_t current = NULL; | ||
| 891 | |||
| 892 | if (!plist) | ||
| 893 | return NULL; | ||
| 894 | |||
| 895 | for (current = (plist_t)g_node_first_child(plist); current; current = (plist_t)g_node_next_sibling(current)) { | ||
| 896 | |||
| 897 | plist_data_t data = plist_get_data(current); | ||
| 898 | |||
| 899 | if (data->type == type && data->length == length && compare_node_value(type, data, value, length)) { | ||
| 900 | return current; | ||
| 901 | } | ||
| 902 | if (data->type == PLIST_DICT || data->type == PLIST_ARRAY) { | ||
| 903 | plist_t sub = plist_find_node(current, type, value, length); | ||
| 904 | if (sub) | ||
| 905 | return sub; | ||
| 906 | } | ||
| 907 | } | ||
| 908 | return NULL; | ||
| 909 | } | ||
| 910 | |||
| 911 | plist_t plist_find_node_by_key(plist_t plist, const char *value) | ||
| 912 | { | ||
| 913 | return plist_find_node(plist, PLIST_KEY, value, strlen(value)); | ||
| 914 | } | ||
| 915 | |||
| 916 | plist_t plist_find_node_by_string(plist_t plist, const char *value) | ||
| 917 | { | ||
| 918 | return plist_find_node(plist, PLIST_STRING, value, strlen(value)); | ||
| 919 | } | ||
| 889 | 920 | ||
