summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Nikias Bassen2017-01-28 04:44:05 +0100
committerGravatar Nikias Bassen2017-01-28 04:44:05 +0100
commit458341fcc360db6e0bac0619e2512e6050f4e8c7 (patch)
tree5be7f4399c4f676a8c5bd8998682a2e02897bbe0
parent6bf56a7cb5e98a4afe4e969d343b9a50681afd97 (diff)
downloadlibplist-458341fcc360db6e0bac0619e2512e6050f4e8c7.tar.gz
libplist-458341fcc360db6e0bac0619e2512e6050f4e8c7.tar.bz2
bplist: Improve real/date node de/serialization
-rw-r--r--src/bplist.c121
1 files changed, 56 insertions, 65 deletions
diff --git a/src/bplist.c b/src/bplist.c
index 9e6e261..a2fb9be 100644
--- a/src/bplist.c
+++ b/src/bplist.c
@@ -75,25 +75,6 @@ enum
75 BPLIST_MASK = 0xF0 75 BPLIST_MASK = 0xF0
76}; 76};
77 77
78static void float_byte_convert(uint8_t * address, size_t size)
79{
80#if (defined(__LITTLE_ENDIAN__) \
81 && !defined(__FLOAT_WORD_ORDER__)) \
82 || (defined(__FLOAT_WORD_ORDER__) \
83 && __FLOAT_WORD_ORDER__ == __ORDER_LITTLE_ENDIAN__)
84 uint8_t i = 0, j = 0;
85 uint8_t tmp = 0;
86
87 for (i = 0; i < (size / 2); i++)
88 {
89 tmp = address[i];
90 j = ((size - 1) + 0) - i;
91 address[i] = address[j];
92 address[j] = tmp;
93 }
94#endif
95}
96
97union plist_uint_ptr 78union plist_uint_ptr
98{ 79{
99 const void *src; 80 const void *src;
@@ -128,11 +109,33 @@ static void byte_convert(uint8_t * address, size_t size)
128#endif 109#endif
129} 110}
130 111
112#ifndef bswap16
113#define bswap16(x) ((((x) & 0xFF00) >> 8) | (((x) & 0x00FF) << 8))
114#endif
115
116#ifndef bswap32
117#define bswap32(x) ((((x) & 0xFF000000) >> 24) \
118 | (((x) & 0x00FF0000) >> 8) \
119 | (((x) & 0x0000FF00) << 8) \
120 | (((x) & 0x000000FF) << 24))
121#endif
122
123#ifndef bswap64
124#define bswap64(x) ((((x) & 0xFF00000000000000ull) >> 56) \
125 | (((x) & 0x00FF000000000000ull) >> 40) \
126 | (((x) & 0x0000FF0000000000ull) >> 24) \
127 | (((x) & 0x000000FF00000000ull) >> 8) \
128 | (((x) & 0x00000000FF000000ull) << 8) \
129 | (((x) & 0x0000000000FF0000ull) << 24) \
130 | (((x) & 0x000000000000FF00ull) << 40) \
131 | (((x) & 0x00000000000000FFull) << 56))
132#endif
133
131#ifndef be16toh 134#ifndef be16toh
132#ifdef __BIG_ENDIAN__ 135#ifdef __BIG_ENDIAN__
133#define be16toh(x) (x) 136#define be16toh(x) (x)
134#else 137#else
135#define be16toh(x) ((((x) & 0xFF00) >> 8) | (((x) & 0x00FF) << 8)) 138#define be16toh(x) bswap16(x)
136#endif 139#endif
137#endif 140#endif
138 141
@@ -140,10 +143,7 @@ static void byte_convert(uint8_t * address, size_t size)
140#ifdef __BIG_ENDIAN__ 143#ifdef __BIG_ENDIAN__
141#define be32toh(x) (x) 144#define be32toh(x) (x)
142#else 145#else
143#define be32toh(x) ((((x) & 0xFF000000) >> 24) \ 146#define be32toh(x) bswap32(x)
144 | (((x) & 0x00FF0000) >> 8) \
145 | (((x) & 0x0000FF00) << 8) \
146 | (((x) & 0x000000FF) << 24))
147#endif 147#endif
148#endif 148#endif
149 149
@@ -151,14 +151,7 @@ static void byte_convert(uint8_t * address, size_t size)
151#ifdef __BIG_ENDIAN__ 151#ifdef __BIG_ENDIAN__
152#define be64toh(x) (x) 152#define be64toh(x) (x)
153#else 153#else
154#define be64toh(x) ((((x) & 0xFF00000000000000ull) >> 56) \ 154#define be64toh(x) bswap64(x)
155 | (((x) & 0x00FF000000000000ull) >> 40) \
156 | (((x) & 0x0000FF0000000000ull) >> 24) \
157 | (((x) & 0x000000FF00000000ull) >> 8) \
158 | (((x) & 0x00000000FF000000ull) << 8) \
159 | (((x) & 0x0000000000FF0000ull) << 24) \
160 | (((x) & 0x000000000000FF00ull) << 40) \
161 | (((x) & 0x00000000000000FFull) << 56))
162#endif 155#endif
163#endif 156#endif
164 157
@@ -186,7 +179,19 @@ static void byte_convert(uint8_t * address, size_t size)
186 ( ((uint64_t)x) < (1ULL << 24) ? 3 : \ 179 ( ((uint64_t)x) < (1ULL << 24) ? 3 : \
187 ( ((uint64_t)x) < (1ULL << 32) ? 4 : 8)))) 180 ( ((uint64_t)x) < (1ULL << 32) ? 4 : 8))))
188 181
189#define get_real_bytes(x) (x == (float) x ? 4 : 8) 182#define get_real_bytes(x) (x == (float) x ? sizeof(float) : sizeof(double))
183
184#if (defined(__LITTLE_ENDIAN__) \
185 && !defined(__FLOAT_WORD_ORDER__)) \
186 || (defined(__FLOAT_WORD_ORDER__) \
187 && __FLOAT_WORD_ORDER__ == __ORDER_LITTLE_ENDIAN__)
188#define float_bswap64(x) bswap64(x)
189#define float_bswap32(x) bswap32(x)
190#else
191#define float_bswap64(x) (x)
192#define float_bswap32(x) (x)
193#endif
194
190 195
191#define NODE_IS_ROOT(x) (((node_t*)x)->isRoot) 196#define NODE_IS_ROOT(x) (((node_t*)x)->isRoot)
192 197
@@ -235,29 +240,23 @@ static plist_t parse_uint_node(const char **bnode, uint8_t size)
235static plist_t parse_real_node(const char **bnode, uint8_t size) 240static plist_t parse_real_node(const char **bnode, uint8_t size)
236{ 241{
237 plist_data_t data = plist_new_plist_data(); 242 plist_data_t data = plist_new_plist_data();
238 float floatval = 0.0; 243 uint8_t buf[8];
239 uint8_t* buf;
240 244
241 size = 1 << size; // make length less misleading 245 size = 1 << size; // make length less misleading
242 buf = malloc (size);
243 memcpy (buf, *bnode, size);
244 switch (size) 246 switch (size)
245 { 247 {
246 case sizeof(float): 248 case sizeof(uint32_t):
247 float_byte_convert(buf, size); 249 *(uint32_t*)buf = float_bswap32(*(uint32_t*)*bnode);
248 floatval = *(float *) buf; 250 data->realval = *(float *) buf;
249 data->realval = floatval;
250 break; 251 break;
251 case sizeof(double): 252 case sizeof(uint64_t):
252 float_byte_convert(buf, size); 253 *(uint64_t*)buf = float_bswap64(*(uint64_t*)*bnode);
253 data->realval = *(double *) buf; 254 data->realval = *(double *) buf;
254 break; 255 break;
255 default: 256 default:
256 free(buf);
257 free(data); 257 free(data);
258 return NULL; 258 return NULL;
259 } 259 }
260 free (buf);
261 data->type = PLIST_REAL; 260 data->type = PLIST_REAL;
262 data->length = sizeof(double); 261 data->length = sizeof(double);
263 262
@@ -872,32 +871,24 @@ static void write_uint(bytearray_t * bplist, uint64_t val)
872 871
873static void write_real(bytearray_t * bplist, double val) 872static void write_real(bytearray_t * bplist, double val)
874{ 873{
875 uint64_t size = get_real_bytes(val); //cheat to know used space 874 int size = get_real_bytes(val); //cheat to know used space
876 uint8_t *buff = (uint8_t *) malloc(sizeof(uint8_t) + size); 875 uint8_t buff[9];
877 buff[0] = BPLIST_REAL | Log2(size); 876 buff[0] = BPLIST_REAL | Log2(size);
878 if (size == sizeof(double)) 877 if (size == sizeof(float)) {
879 { 878 float floatval = (float)val;
880 memcpy(buff + 1, &val, size); 879 *(uint32_t*)(buff+1) = float_bswap32(*(uint32_t*)&floatval);
881 } 880 } else {
882 else if (size == sizeof(float)) 881 *(uint64_t*)(buff+1) = float_bswap64(*(uint64_t*)&val);
883 {
884 float tmpval = (float) val;
885 memcpy(buff + 1, &tmpval, size);
886 } 882 }
887 float_byte_convert(buff + 1, size); 883 byte_array_append(bplist, buff, size+1);
888 byte_array_append(bplist, buff, sizeof(uint8_t) + size);
889 free(buff);
890} 884}
891 885
892static void write_date(bytearray_t * bplist, double val) 886static void write_date(bytearray_t * bplist, double val)
893{ 887{
894 uint64_t size = 8; //dates always use 8 bytes 888 uint8_t buff[9];
895 uint8_t *buff = (uint8_t *) malloc(sizeof(uint8_t) + size); 889 buff[0] = BPLIST_DATE | 3;
896 buff[0] = BPLIST_DATE | Log2(size); 890 *(uint64_t*)(buff+1) = float_bswap64(*(uint64_t*)&val);
897 memcpy(buff + 1, &val, size); 891 byte_array_append(bplist, buff, sizeof(buff));
898 float_byte_convert(buff + 1, size);
899 byte_array_append(bplist, buff, sizeof(uint8_t) + size);
900 free(buff);
901} 892}
902 893
903static void write_raw_data(bytearray_t * bplist, uint8_t mark, uint8_t * val, uint64_t size) 894static void write_raw_data(bytearray_t * bplist, uint8_t mark, uint8_t * val, uint64_t size)