From 817749dd4e27768da64e3883fe04580cd22461a8 Mon Sep 17 00:00:00 2001 From: Nikias Bassen Date: Sun, 16 Sep 2012 06:03:57 +0200 Subject: implemented handling of UID keyed encoding type --- include/plist/plist.h | 28 ++++++++++++++++++++++++ src/bplist.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++++-- src/plist.c | 27 +++++++++++++++++++++++ src/xplist.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 168 insertions(+), 2 deletions(-) diff --git a/include/plist/plist.h b/include/plist/plist.h index 1b1ac52..546e108 100644 --- a/include/plist/plist.h +++ b/include/plist/plist.h @@ -83,6 +83,7 @@ extern "C" PLIST_DATE, /**< Date, scalar type */ PLIST_DATA, /**< Binary data, scalar type */ PLIST_KEY, /**< Key in dictionaries (ASCII String), scalar type */ + PLIST_UID, /**< Special type used for 'keyed encoding' */ PLIST_NONE /**< No type */ } plist_type; @@ -165,6 +166,15 @@ extern "C" */ PLIST_API plist_t plist_new_date(int32_t sec, int32_t usec); + /** + * Create a new plist_t type #PLIST_UID + * + * @param val the unsigned integer value + * @return the created item + * @sa #plist_type + */ + PLIST_API plist_t plist_new_uid(uint64_t val); + /** * Destruct a plist_t node and all its children recursively * @@ -416,6 +426,15 @@ extern "C" */ PLIST_API void plist_get_date_val(plist_t node, int32_t * sec, int32_t * usec); + /** + * Get the value of a #PLIST_UID node. + * This function does nothing if node is not of type #PLIST_UID + * + * @param node the node + * @param val a pointer to a uint64_t variable. + */ + PLIST_API void plist_get_uid_val(plist_t node, uint64_t * val); + /******************************************** * * @@ -496,6 +515,15 @@ extern "C" */ PLIST_API void plist_set_date_val(plist_t node, int32_t sec, int32_t usec); + /** + * Set the value of a node. + * Forces type of node to #PLIST_UID + * + * @param node the node + * @param val the unsigned integer value + */ + PLIST_API void plist_set_uid_val(plist_t node, uint64_t val); + /******************************************** * * diff --git a/src/bplist.c b/src/bplist.c index eff44fc..7893ff5 100644 --- a/src/bplist.c +++ b/src/bplist.c @@ -63,7 +63,8 @@ enum BPLIST_DATA = 0x40, BPLIST_STRING = 0x50, BPLIST_UNICODE = 0x60, - BPLIST_UID = 0x70, + BPLIST_UNK_0x70 = 0x70, + BPLIST_UID = 0x80, BPLIST_ARRAY = 0xA0, BPLIST_SET = 0xC0, BPLIST_DICT = 0xD0, @@ -375,6 +376,31 @@ static plist_t parse_array_node(char *bnode, uint64_t size, uint32_t ref_size) return node_create(NULL, data); } +static plist_t parse_uid_node(char *bnode, uint8_t size, char **next_object) +{ + plist_data_t data = plist_new_plist_data(); + + size = 1 << size; // make length less misleading + switch (size) + { + case sizeof(uint8_t): + case sizeof(uint16_t): + case sizeof(uint32_t): + case sizeof(uint64_t): + memcpy(&data->intval, bnode, size); + data->intval = UINT_TO_HOST(&data->intval, size); + break; + default: + free(data); + return NULL; + }; + + *next_object = bnode + size; + data->type = PLIST_UID; + data->length = sizeof(uint64_t); + + return node_create(NULL, data); +} static plist_t parse_bin_node(char *object, uint8_t dict_size, char **next_object) @@ -464,7 +490,7 @@ static plist_t parse_bin_node(char *object, uint8_t dict_size, char **next_objec } return parse_unicode_node(object, size); - case BPLIST_UID: + case BPLIST_UNK_0x70: case BPLIST_ARRAY: if (0x0F == size) { @@ -476,6 +502,9 @@ static plist_t parse_bin_node(char *object, uint8_t dict_size, char **next_objec } return parse_array_node(object, size, dict_size); + case BPLIST_UID: + return parse_uid_node(object, size, next_object); + case BPLIST_SET: case BPLIST_DICT: if (0x0F == size) @@ -528,6 +557,9 @@ static void* copy_plist_data(const void* src) dstdata->buff = (uint8_t*) malloc(sizeof(uint8_t) * srcdata->length * 2); memcpy(dstdata->buff, srcdata->buff, sizeof(uint8_t) * srcdata->length * 2); break; + case PLIST_UID: + dstdata->intval = srcdata->intval; + break; default: break; } @@ -672,6 +704,7 @@ static unsigned int plist_data_hash(const void* key) case PLIST_BOOLEAN: case PLIST_UINT: case PLIST_REAL: + case PLIST_UID: buff = (char *) &data->intval; //works also for real as we use an union size = 8; break; @@ -916,6 +949,26 @@ static void write_dict(bytearray_t * bplist, node_t* node, hashtable_t* ref_tabl } +static void write_uid(bytearray_t * bplist, uint64_t val) +{ + uint64_t size = get_needed_bytes(val); + uint8_t *buff = NULL; + //do not write 3bytes int node + if (size == 3) + size++; + +#if PLIST_BYTE_ORDER == PLIST_BIG_ENDIAN + val = val << ((sizeof(uint64_t) - size) * 8); +#endif + + buff = (uint8_t *) malloc(sizeof(uint8_t) + size); + buff[0] = BPLIST_UID | Log2(size); + memcpy(buff + 1, &val, size); + byte_convert(buff + 1, size); + byte_array_append(bplist, buff, sizeof(uint8_t) + size); + free(buff); +} + static int is_ascii_string(char* s, int len) { int ret = 1, i = 0; @@ -1074,6 +1127,9 @@ void plist_to_bin(plist_t plist, char **plist_bin, uint32_t * length) case PLIST_DATE: write_date(bplist_buff, data->timeval.tv_sec + (double) data->timeval.tv_usec / 1000000); break; + case PLIST_UID: + write_uid(bplist_buff, data->intval); + break; default: break; } diff --git a/src/plist.c b/src/plist.c index 2b31fdd..ee79cf4 100644 --- a/src/plist.c +++ b/src/plist.c @@ -138,6 +138,15 @@ plist_t plist_new_uint(uint64_t val) return plist_new_node(data); } +plist_t plist_new_uid(uint64_t val) +{ + plist_data_t data = plist_new_plist_data(); + data->type = PLIST_UID; + data->intval = val; + data->length = sizeof(uint64_t); + return plist_new_node(data); +} + plist_t plist_new_real(double val) { plist_data_t data = plist_new_plist_data(); @@ -490,6 +499,7 @@ static void plist_get_type_and_value(plist_t node, plist_type * type, void *valu *((char *) value) = data->boolval; break; case PLIST_UINT: + case PLIST_UID: *((uint64_t *) value) = data->intval; break; case PLIST_REAL: @@ -567,6 +577,15 @@ void plist_get_uint_val(plist_t node, uint64_t * val) assert(length == sizeof(uint64_t)); } +void plist_get_uid_val(plist_t node, uint64_t * val) +{ + plist_type type = plist_get_node_type(node); + uint64_t length = 0; + if (PLIST_UID == type) + plist_get_type_and_value(node, &type, (void *) val, &length); + assert(length == sizeof(uint64_t)); +} + void plist_get_real_val(plist_t node, double *val) { plist_type type = plist_get_node_type(node); @@ -617,6 +636,7 @@ int plist_data_compare(const void *a, const void *b) case PLIST_BOOLEAN: case PLIST_UINT: case PLIST_REAL: + case PLIST_UID: if (val_a->intval == val_b->intval) //it is an union so this is sufficient return TRUE; else @@ -690,6 +710,7 @@ static void plist_set_element_val(plist_t node, plist_type type, const void *val data->boolval = *((char *) value); break; case PLIST_UINT: + case PLIST_UID: data->intval = *((uint64_t *) value); break; case PLIST_REAL: @@ -728,6 +749,7 @@ void plist_set_type(plist_t node, plist_type type) data->length = sizeof(uint8_t); break; case PLIST_UINT: + case PLIST_UID: data->length = sizeof(uint64_t); break; case PLIST_REAL: @@ -763,6 +785,11 @@ void plist_set_uint_val(plist_t node, uint64_t val) plist_set_element_val(node, PLIST_UINT, &val, sizeof(uint64_t)); } +void plist_set_uid_val(plist_t node, uint64_t val) +{ + plist_set_element_val(node, PLIST_UID, &val, sizeof(uint64_t)); +} + void plist_set_real_val(plist_t node, double val) { plist_set_element_val(node, PLIST_REAL, &val, sizeof(double)); diff --git a/src/xplist.c b/src/xplist.c index ba312a1..b551179 100644 --- a/src/xplist.c +++ b/src/xplist.c @@ -126,6 +126,25 @@ static xmlDocPtr new_xml_plist(void) return plist_xml; } +static struct node_t* new_key_node(const char* name) +{ + plist_data_t data = plist_new_plist_data(); + data->type = PLIST_KEY; + int size = strlen(name); + data->strval = strdup(name); + data->length = size; + return node_create(NULL, data); +} + +static struct node_t* new_uint_node(uint64_t uint) +{ + plist_data_t data = plist_new_plist_data(); + data->type = PLIST_UINT; + data->intval = uint; + data->length = sizeof(uint64_t); + return node_create(NULL, data); +} + static void node_to_xml(node_t* node, void *xml_struct) { struct xml_node *xstruct = NULL; @@ -133,6 +152,7 @@ static void node_to_xml(node_t* node, void *xml_struct) xmlNodePtr child_node = NULL; char isStruct = FALSE; + char isUIDNode = FALSE; const xmlChar *tag = NULL; char *val = NULL; @@ -214,6 +234,15 @@ static void node_to_xml(node_t* node, void *xml_struct) } } break; + case PLIST_UID: + // special case for keyed encoding + tag = XPLIST_DICT; + isStruct = TRUE; + isUIDNode = TRUE; + node_data->type = PLIST_DICT; + node_attach(node, new_key_node("CF$UID")); + node_attach(node, new_uint_node(node_data->intval)); + break; default: break; } @@ -256,6 +285,17 @@ static void node_to_xml(node_t* node, void *xml_struct) xmlNodeAddContent(child_node, BAD_CAST("\t")); } } + if (isUIDNode) + { + unsigned int num = node_n_children(node); + unsigned int i; + for (i = num; i > 0; i--) { + node_t* ch = node_nth_child(node, i-1); + node_detach(node, ch); + node_destroy(ch); + } + node_data->type = PLIST_UID; + } return; } @@ -406,6 +446,21 @@ static void xml_to_node(xmlNodePtr xml_node, plist_t * plist_node) { data->type = PLIST_DICT; xml_to_node(node, &subnode); + if (plist_get_node_type(subnode) == PLIST_DICT) { + if (plist_dict_get_size(subnode) == 1) { + plist_t uid = plist_dict_get_item(subnode, "CF$UID"); + if (uid) { + uint64_t val = 0; + plist_get_uint_val(uid, &val); + plist_dict_remove_item(subnode, "CF$UID"); + plist_data_t nodedata = plist_get_data((node_t*)subnode); + free(nodedata->buff); + nodedata->type = PLIST_UID; + nodedata->length = sizeof(uint64_t); + nodedata->intval = val; + } + } + } continue; } } -- cgit v1.1-32-gdbae