From d886885b0ec2506fa2caf0986a3d0e496fea91c2 Mon Sep 17 00:00:00 2001 From: Nikias Bassen Date: Mon, 16 Jan 2023 04:25:52 +0100 Subject: Rename PLIST_UINT to PLIST_INT and add plist_new_int() and plist_get_int_val() This properly supports getting and setting signed or unsigned integer values. Also, a new helper function plist_int_val_is_negative() was added to determine if a given #PLIST_INT node has a negative value or not. The old type PLIST_UINT is defined as a macro with the value of PLIST_INT for backwards compatibility. This commit also adds int vs. uint support to the C++ interface, and the python bindings in a hopefully useful way. --- src/Integer.cpp | 35 +++++++++++++++++++++++++---- src/Key.cpp | 2 +- src/Node.cpp | 4 ++-- src/Real.cpp | 2 +- src/String.cpp | 2 +- src/bplist.c | 24 ++++++++++---------- src/jplist.c | 12 ++++++---- src/oplist.c | 4 ++-- src/plist.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++------- src/xplist.c | 6 ++--- 10 files changed, 121 insertions(+), 38 deletions(-) (limited to 'src') diff --git a/src/Integer.cpp b/src/Integer.cpp index a40d026..7fa0f93 100644 --- a/src/Integer.cpp +++ b/src/Integer.cpp @@ -24,7 +24,7 @@ namespace PList { -Integer::Integer(Node* parent) : Node(PLIST_UINT, parent) +Integer::Integer(Node* parent) : Node(PLIST_INT, parent) { } @@ -32,7 +32,7 @@ Integer::Integer(plist_t node, Node* parent) : Node(node, parent) { } -Integer::Integer(const PList::Integer& i) : Node(PLIST_UINT) +Integer::Integer(const PList::Integer& i) : Node(PLIST_INT) { plist_set_uint_val(_node, i.GetValue()); } @@ -44,11 +44,16 @@ Integer& Integer::operator=(const PList::Integer& i) return *this; } -Integer::Integer(uint64_t i) : Node(PLIST_UINT) +Integer::Integer(uint64_t i) : Node(PLIST_INT) { plist_set_uint_val(_node, i); } +Integer::Integer(int64_t i) : Node(PLIST_INT) +{ + plist_set_int_val(_node, i); +} + Integer::~Integer() { } @@ -58,16 +63,38 @@ Node* Integer::Clone() const return new Integer(*this); } +void Integer::SetValue(int64_t i) +{ + plist_set_int_val(_node, i); +} + void Integer::SetValue(uint64_t i) { plist_set_uint_val(_node, i); } -uint64_t Integer::GetValue() const +void Integer::SetUnsignedValue(uint64_t i) +{ + plist_set_uint_val(_node, i); +} + +int64_t Integer::GetValue() const +{ + int64_t i = 0; + plist_get_int_val(_node, &i); + return i; +} + +uint64_t Integer::GetUnsignedValue() const { uint64_t i = 0; plist_get_uint_val(_node, &i); return i; } +bool Integer::isNegative() const +{ + return plist_int_val_is_negative(_node); +} + } // namespace PList diff --git a/src/Key.cpp b/src/Key.cpp index 5d7d372..5f8d205 100644 --- a/src/Key.cpp +++ b/src/Key.cpp @@ -32,7 +32,7 @@ Key::Key(plist_t node, Node* parent) : Node(node, parent) { } -Key::Key(const PList::Key& k) : Node(PLIST_UINT) +Key::Key(const PList::Key& k) : Node(PLIST_INT) { plist_set_key_val(_node, k.GetValue().c_str()); } diff --git a/src/Node.cpp b/src/Node.cpp index fb79911..08a91b0 100644 --- a/src/Node.cpp +++ b/src/Node.cpp @@ -52,7 +52,7 @@ Node::Node(plist_type type, Node* parent) : _parent(parent) case PLIST_BOOLEAN: _node = plist_new_bool(0); break; - case PLIST_UINT: + case PLIST_INT: _node = plist_new_uint(0); break; case PLIST_REAL: @@ -134,7 +134,7 @@ Node* Node::FromPlist(plist_t node, Node* parent) case PLIST_BOOLEAN: ret = new Boolean(node, parent); break; - case PLIST_UINT: + case PLIST_INT: ret = new Integer(node, parent); break; case PLIST_REAL: diff --git a/src/Real.cpp b/src/Real.cpp index 6bdb920..02d1d9b 100644 --- a/src/Real.cpp +++ b/src/Real.cpp @@ -32,7 +32,7 @@ Real::Real(plist_t node, Node* parent) : Node(node, parent) { } -Real::Real(const PList::Real& d) : Node(PLIST_UINT) +Real::Real(const PList::Real& d) : Node(PLIST_INT) { plist_set_real_val(_node, d.GetValue()); } diff --git a/src/String.cpp b/src/String.cpp index 06b61ba..aee2358 100644 --- a/src/String.cpp +++ b/src/String.cpp @@ -32,7 +32,7 @@ String::String(plist_t node, Node* parent) : Node(node, parent) { } -String::String(const PList::String& s) : Node(PLIST_UINT) +String::String(const PList::String& s) : Node(PLIST_INT) { plist_set_string_val(_node, s.GetValue().c_str()); } diff --git a/src/bplist.c b/src/bplist.c index 851ecd6..8927de6 100644 --- a/src/bplist.c +++ b/src/bplist.c @@ -62,7 +62,7 @@ enum BPLIST_FALSE = 0x08, BPLIST_TRUE = 0x09, BPLIST_FILL = 0x0F, /* will be used for length grabbing */ - BPLIST_UINT = 0x10, + BPLIST_INT = 0x10, BPLIST_REAL = 0x20, BPLIST_DATE = 0x30, BPLIST_DATA = 0x40, @@ -229,7 +229,7 @@ void plist_bin_deinit(void) static plist_t parse_bin_node_at_index(struct bplist_data *bplist, uint32_t node_index); -static plist_t parse_uint_node(const char **bnode, uint8_t size) +static plist_t parse_int_node(const char **bnode, uint8_t size) { plist_data_t data = plist_new_plist_data(); @@ -254,7 +254,7 @@ static plist_t parse_uint_node(const char **bnode, uint8_t size) data->intval = UINT_TO_HOST(*bnode, size); (*bnode) += size; - data->type = PLIST_UINT; + data->type = PLIST_INT; return node_create(NULL, data); } @@ -583,8 +583,8 @@ static plist_t parse_bin_node(struct bplist_data *bplist, const char** object) case BPLIST_DICT: { uint16_t next_size = **object & BPLIST_FILL; - if ((**object & BPLIST_MASK) != BPLIST_UINT) { - PLIST_BIN_ERR("%s: invalid size node type for node type 0x%02x: found 0x%02x, expected 0x%02x\n", __func__, type, **object & BPLIST_MASK, BPLIST_UINT); + if ((**object & BPLIST_MASK) != BPLIST_INT) { + PLIST_BIN_ERR("%s: invalid size node type for node type 0x%02x: found 0x%02x, expected 0x%02x\n", __func__, type, **object & BPLIST_MASK, BPLIST_INT); return NULL; } (*object)++; @@ -641,12 +641,12 @@ static plist_t parse_bin_node(struct bplist_data *bplist, const char** object) return NULL; } - case BPLIST_UINT: + case BPLIST_INT: if (pobject + (uint64_t)(1 << size) > poffset_table) { - PLIST_BIN_ERR("%s: BPLIST_UINT data bytes point outside of valid range\n", __func__); + PLIST_BIN_ERR("%s: BPLIST_INT data bytes point outside of valid range\n", __func__); return NULL; } - return parse_uint_node(object, size); + return parse_int_node(object, size); case BPLIST_REAL: if (pobject + (uint64_t)(1 << size) > poffset_table) { @@ -896,7 +896,7 @@ static unsigned int plist_data_hash(const void* key) switch (data->type) { case PLIST_BOOLEAN: - case PLIST_UINT: + case PLIST_INT: case PLIST_REAL: case PLIST_DATE: case PLIST_UID: @@ -973,7 +973,7 @@ static void write_int(bytearray_t * bplist, uint64_t val) //do not write 3bytes int node if (size == 3) size++; - sz = BPLIST_UINT | Log2(size); + sz = BPLIST_INT | Log2(size); val = be64toh(val); byte_array_append(bplist, &sz, 1); @@ -982,7 +982,7 @@ static void write_int(bytearray_t * bplist, uint64_t val) static void write_uint(bytearray_t * bplist, uint64_t val) { - uint8_t sz = BPLIST_UINT | 4; + uint8_t sz = BPLIST_INT | 4; uint64_t zero = 0; val = be64toh(val); @@ -1346,7 +1346,7 @@ PLIST_API plist_err_t plist_to_bin(plist_t plist, char **plist_bin, uint32_t * l byte_array_append(bplist_buff, &b, 1); break; } - case PLIST_UINT: + case PLIST_INT: if (data->length == 16) { write_uint(bplist_buff, data->intval); } else { diff --git a/src/jplist.c b/src/jplist.c index f4adf2f..7817b1c 100644 --- a/src/jplist.c +++ b/src/jplist.c @@ -131,7 +131,7 @@ static int node_to_json(node_t* node, bytearray_t **outbuf, uint32_t depth, int str_buf_append(*outbuf, "null", 4); break; - case PLIST_UINT: + case PLIST_INT: val = (char*)malloc(64); if (node_data->length == 16) { val_len = snprintf(val, 64, "%"PRIu64, node_data->intval); @@ -349,7 +349,7 @@ static int node_estimate_size(node_t *node, uint64_t *size, uint32_t depth, int *size += data->length; *size += 2; break; - case PLIST_UINT: + case PLIST_INT: if (data->length == 16) { *size += num_digits_u(data->intval); } else { @@ -501,10 +501,15 @@ static plist_t parse_primitive(const char* js, jsmntok_info_t* ti, int* index) val = plist_new_node(data); } else if (isdigit(str_val[0]) || (str_val[0] == '-' && str_val+1 < str_end && isdigit(str_val[1]))) { char* endp = (char*)str_val; + int is_neg = (str_val[0] == '-'); int64_t intpart = parse_decimal(str_val, str_end, &endp); if (endp >= str_end) { /* integer */ - val = plist_new_uint((uint64_t)intpart); + if (is_neg || intpart <= INT64_MAX) { + val = plist_new_int(intpart); + } else { + val = plist_new_uint((uint64_t)intpart); + } } else if ((*endp == '.' && endp+1 < str_end && isdigit(*(endp+1))) || ((*endp == 'e' || *endp == 'E') && endp+1 < str_end && (isdigit(*(endp+1)) || ((*(endp+1) == '-') && endp+2 < str_end && isdigit(*(endp+2)))))) { /* floating point */ double dval = (double)intpart; @@ -513,7 +518,6 @@ static plist_t parse_primitive(const char* js, jsmntok_info_t* ti, int* index) do { if (*endp == '.') { fendp++; - int is_neg = (str_val[0] == '-'); double frac = 0; double p = 0.1; while (fendp < str_end && isdigit(*fendp)) { diff --git a/src/oplist.c b/src/oplist.c index 122440f..8936cce 100644 --- a/src/oplist.c +++ b/src/oplist.c @@ -146,7 +146,7 @@ static int node_to_openstep(node_t* node, bytearray_t **outbuf, uint32_t depth, switch (node_data->type) { - case PLIST_UINT: + case PLIST_INT: val = (char*)malloc(64); if (node_data->length == 16) { val_len = snprintf(val, 64, "%"PRIu64, node_data->intval); @@ -393,7 +393,7 @@ static int node_estimate_size(node_t *node, uint64_t *size, uint32_t depth, int *size += data->length; *size += 2; break; - case PLIST_UINT: + case PLIST_INT: if (data->length == 16) { *size += num_digits_u(data->intval); } else { diff --git a/src/plist.c b/src/plist.c index e696f70..5d06311 100644 --- a/src/plist.c +++ b/src/plist.c @@ -2,7 +2,7 @@ * plist.c * Builds plist XML structures * - * Copyright (c) 2009-2019 Nikias Bassen, All Rights Reserved. + * Copyright (c) 2009-2023 Nikias Bassen, All Rights Reserved. * Copyright (c) 2010-2015 Martin Szulecki, All Rights Reserved. * Copyright (c) 2008 Zach C., All Rights Reserved. * @@ -390,7 +390,16 @@ PLIST_API plist_t plist_new_bool(uint8_t val) PLIST_API plist_t plist_new_uint(uint64_t val) { plist_data_t data = plist_new_plist_data(); - data->type = PLIST_UINT; + data->type = PLIST_INT; + data->intval = val; + data->length = (val > INT_MAX) ? sizeof(uint64_t)*2 : sizeof(uint64_t); + return plist_new_node(data); +} + +PLIST_API plist_t plist_new_int(int64_t val) +{ + plist_data_t data = plist_new_plist_data(); + data->type = PLIST_INT; data->intval = val; data->length = sizeof(uint64_t); return plist_new_node(data); @@ -926,7 +935,7 @@ static void plist_get_type_and_value(plist_t node, plist_type * type, void *valu case PLIST_BOOLEAN: *((char *) value) = data->boolval; break; - case PLIST_UINT: + case PLIST_INT: case PLIST_UID: *((uint64_t *) value) = data->intval; break; @@ -1024,12 +1033,17 @@ PLIST_API void plist_get_uint_val(plist_t node, uint64_t * val) return; plist_type type = plist_get_node_type(node); uint64_t length = 0; - if (PLIST_UINT != type) + if (PLIST_INT != type) return; plist_get_type_and_value(node, &type, (void *) val, &length); assert(length == sizeof(uint64_t) || length == 16); } +PLIST_API void plist_get_int_val(plist_t node, int64_t * val) +{ + plist_get_uint_val(node, (uint64_t*)val); +} + PLIST_API void plist_get_uid_val(plist_t node, uint64_t * val) { if (!node || !val) @@ -1116,7 +1130,7 @@ int plist_data_compare(const void *a, const void *b) switch (val_a->type) { case PLIST_BOOLEAN: - case PLIST_UINT: + case PLIST_INT: case PLIST_REAL: case PLIST_DATE: case PLIST_UID: @@ -1180,7 +1194,7 @@ static void plist_set_element_val(plist_t node, plist_type type, const void *val case PLIST_BOOLEAN: data->boolval = *((char *) value); break; - case PLIST_UINT: + case PLIST_INT: case PLIST_UID: data->intval = *((uint64_t *) value); break; @@ -1225,7 +1239,12 @@ PLIST_API void plist_set_bool_val(plist_t node, uint8_t val) PLIST_API void plist_set_uint_val(plist_t node, uint64_t val) { - plist_set_element_val(node, PLIST_UINT, &val, sizeof(uint64_t)); + plist_set_element_val(node, PLIST_INT, &val, (val > INT64_MAX) ? sizeof(uint64_t)*2 : sizeof(uint64_t)); +} + +PLIST_API void plist_set_int_val(plist_t node, int64_t val) +{ + plist_set_element_val(node, PLIST_INT, &val, sizeof(uint64_t)); } PLIST_API void plist_set_uid_val(plist_t node, uint64_t val) @@ -1259,9 +1278,42 @@ PLIST_API int plist_bool_val_is_true(plist_t boolnode) return (bv == 1); } +PLIST_API int plist_int_val_is_negative(plist_t intnode) +{ + if (!PLIST_IS_INT(intnode)) { + return 0; + } + plist_data_t data = plist_get_data(intnode); + if (data->length == 16) { + return 0; + } + if ((int64_t)data->intval < 0) { + return 1; + } + return 0; +} + +PLIST_API int plist_int_val_compare(plist_t uintnode, int64_t cmpval) +{ + if (!PLIST_IS_INT(uintnode)) { + return -1; + } + int64_t uintval = 0; + plist_get_int_val(uintnode, &uintval); + if (uintval == cmpval) { + return 0; + } + + if (uintval < cmpval) { + return -1; + } + + return 1; +} + PLIST_API int plist_uint_val_compare(plist_t uintnode, uint64_t cmpval) { - if (!PLIST_IS_UINT(uintnode)) { + if (!PLIST_IS_INT(uintnode)) { return -1; } uint64_t uintval = 0; diff --git a/src/xplist.c b/src/xplist.c index d8f6458..cf5d818 100644 --- a/src/xplist.c +++ b/src/xplist.c @@ -162,7 +162,7 @@ static int node_to_xml(node_t* node, bytearray_t **outbuf, uint32_t depth) } break; - case PLIST_UINT: + case PLIST_INT: tag = XPLIST_INT; tag_len = XPLIST_INT_LEN; val = (char*)malloc(64); @@ -479,7 +479,7 @@ static int node_estimate_size(node_t *node, uint64_t *size, uint32_t depth) *size += data->length; *size += (XPLIST_KEY_LEN << 1) + 6; break; - case PLIST_UINT: + case PLIST_INT: if (data->length == 16) { *size += num_digits_u(data->intval); } else { @@ -1194,7 +1194,7 @@ static int node_from_xml(parse_ctx ctx, plist_t *plist) data->intval = 0; data->length = 8; } - data->type = PLIST_UINT; + data->type = PLIST_INT; } else if (!strcmp(tag, XPLIST_REAL)) { if (!is_empty) { text_part_t first_part = { NULL, 0, 0, NULL }; -- cgit v1.1-32-gdbae