diff options
Diffstat (limited to 'src/bplist.c')
| -rw-r--r-- | src/bplist.c | 76 |
1 files changed, 63 insertions, 13 deletions
diff --git a/src/bplist.c b/src/bplist.c index 5618c38..0e248f4 100644 --- a/src/bplist.c +++ b/src/bplist.c | |||
| @@ -79,6 +79,24 @@ static void float_byte_convert(uint8_t * address, size_t size) | |||
| 79 | #endif | 79 | #endif |
| 80 | } | 80 | } |
| 81 | 81 | ||
| 82 | union plist_uint_ptr | ||
| 83 | { | ||
| 84 | void *src; | ||
| 85 | uint8_t *u8ptr; | ||
| 86 | uint16_t *u16ptr; | ||
| 87 | uint32_t *u32ptr; | ||
| 88 | uint64_t *u64ptr; | ||
| 89 | }; | ||
| 90 | |||
| 91 | #define get_unaligned(ptr) \ | ||
| 92 | ({ \ | ||
| 93 | struct __attribute__((packed)) { \ | ||
| 94 | typeof(*(ptr)) __v; \ | ||
| 95 | } *__p = (void *) (ptr); \ | ||
| 96 | __p->__v; \ | ||
| 97 | }) | ||
| 98 | |||
| 99 | |||
| 82 | static void byte_convert(uint8_t * address, size_t size) | 100 | static void byte_convert(uint8_t * address, size_t size) |
| 83 | { | 101 | { |
| 84 | #if G_BYTE_ORDER == G_LITTLE_ENDIAN | 102 | #if G_BYTE_ORDER == G_LITTLE_ENDIAN |
| @@ -95,23 +113,36 @@ static void byte_convert(uint8_t * address, size_t size) | |||
| 95 | #endif | 113 | #endif |
| 96 | } | 114 | } |
| 97 | 115 | ||
| 98 | static uint32_t uint24_from_be(char *buff) | 116 | static uint32_t uint24_from_be(union plist_uint_ptr buf) |
| 99 | { | 117 | { |
| 118 | union plist_uint_ptr tmp; | ||
| 100 | uint32_t ret = 0; | 119 | uint32_t ret = 0; |
| 101 | uint8_t *tmp = (uint8_t *) &ret; | 120 | |
| 102 | memcpy(tmp + 1, buff, 3 * sizeof(char)); | 121 | tmp.src = &ret; |
| 103 | byte_convert(tmp, sizeof(uint32_t)); | 122 | |
| 123 | memcpy(tmp.u8ptr + 1, buf.u8ptr, 3 * sizeof(char)); | ||
| 124 | |||
| 125 | byte_convert(tmp.u8ptr, sizeof(uint32_t)); | ||
| 104 | return ret; | 126 | return ret; |
| 105 | } | 127 | } |
| 106 | 128 | ||
| 107 | #define UINT_TO_HOST(x, n) \ | 129 | #define UINT_TO_HOST(x, n) \ |
| 108 | (n == 8 ? GUINT64_FROM_BE( *(uint64_t *)(x) ) : \ | 130 | ({ \ |
| 109 | (n == 4 ? GUINT32_FROM_BE( *(uint32_t *)(x) ) : \ | 131 | union plist_uint_ptr __up; \ |
| 110 | (n == 3 ? uint24_from_be( (char*)x ) : \ | 132 | __up.src = x; \ |
| 111 | (n == 2 ? GUINT16_FROM_BE( *(uint16_t *)(x) ) : \ | 133 | (n == 8 ? GUINT64_FROM_BE( get_unaligned(__up.u64ptr) ) : \ |
| 112 | *(uint8_t *)(x) )))) | 134 | (n == 4 ? GUINT32_FROM_BE( get_unaligned(__up.u32ptr) ) : \ |
| 113 | 135 | (n == 3 ? uint24_from_be( __up ) : \ | |
| 114 | #define be64dec(x) GUINT64_FROM_BE( *(uint64_t*)(x) ) | 136 | (n == 2 ? GUINT16_FROM_BE( get_unaligned(__up.u16ptr) ) : \ |
| 137 | *__up.u8ptr )))); \ | ||
| 138 | }) | ||
| 139 | |||
| 140 | #define be64dec(x) \ | ||
| 141 | ({ \ | ||
| 142 | union plist_uint_ptr __up; \ | ||
| 143 | __up.src = x; \ | ||
| 144 | GUINT64_FROM_BE( get_unaligned(__up.u64ptr) ); \ | ||
| 145 | }) | ||
| 115 | 146 | ||
| 116 | #define get_needed_bytes(x) \ | 147 | #define get_needed_bytes(x) \ |
| 117 | ( ((uint64_t)x) < (1ULL << 8) ? 1 : \ | 148 | ( ((uint64_t)x) < (1ULL << 8) ? 1 : \ |
| @@ -646,6 +677,11 @@ static void write_int(GByteArray * bplist, uint64_t val) | |||
| 646 | //do not write 3bytes int node | 677 | //do not write 3bytes int node |
| 647 | if (size == 3) | 678 | if (size == 3) |
| 648 | size++; | 679 | size++; |
| 680 | |||
| 681 | #if G_BYTE_ORDER == G_BIG_ENDIAN | ||
| 682 | val = val << ((sizeof(uint64_t) - size) * 8); | ||
| 683 | #endif | ||
| 684 | |||
| 649 | buff = (uint8_t *) malloc(sizeof(uint8_t) + size); | 685 | buff = (uint8_t *) malloc(sizeof(uint8_t) + size); |
| 650 | buff[0] = BPLIST_UINT | Log2(size); | 686 | buff[0] = BPLIST_UINT | Log2(size); |
| 651 | memcpy(buff + 1, &val, size); | 687 | memcpy(buff + 1, &val, size); |
| @@ -656,7 +692,7 @@ static void write_int(GByteArray * bplist, uint64_t val) | |||
| 656 | 692 | ||
| 657 | static void write_real(GByteArray * bplist, double val) | 693 | static void write_real(GByteArray * bplist, double val) |
| 658 | { | 694 | { |
| 659 | uint64_t size = get_real_bytes(*((uint64_t *) & val)); //cheat to know used space | 695 | uint64_t size = get_real_bytes(val); //cheat to know used space |
| 660 | uint8_t *buff = (uint8_t *) malloc(sizeof(uint8_t) + size); | 696 | uint8_t *buff = (uint8_t *) malloc(sizeof(uint8_t) + size); |
| 661 | buff[0] = BPLIST_REAL | Log2(size); | 697 | buff[0] = BPLIST_REAL | Log2(size); |
| 662 | if (size == sizeof(double)) | 698 | if (size == sizeof(double)) |
| @@ -748,6 +784,9 @@ static void write_array(GByteArray * bplist, GNode * node, GHashTable * ref_tabl | |||
| 748 | for (i = 0, cur = node->children; cur && i < size; cur = cur->next, i++) | 784 | for (i = 0, cur = node->children; cur && i < size; cur = cur->next, i++) |
| 749 | { | 785 | { |
| 750 | idx = *(uint64_t *) (g_hash_table_lookup(ref_table, cur)); | 786 | idx = *(uint64_t *) (g_hash_table_lookup(ref_table, cur)); |
| 787 | #if G_BYTE_ORDER == G_BIG_ENDIAN | ||
| 788 | idx = idx << ((sizeof(uint64_t) - dict_param_size) * 8); | ||
| 789 | #endif | ||
| 751 | memcpy(buff + i * dict_param_size, &idx, dict_param_size); | 790 | memcpy(buff + i * dict_param_size, &idx, dict_param_size); |
| 752 | byte_convert(buff + i * dict_param_size, dict_param_size); | 791 | byte_convert(buff + i * dict_param_size, dict_param_size); |
| 753 | } | 792 | } |
| @@ -783,10 +822,16 @@ static void write_dict(GByteArray * bplist, GNode * node, GHashTable * ref_table | |||
| 783 | for (i = 0, cur = node->children; cur && i < size; cur = cur->next->next, i++) | 822 | for (i = 0, cur = node->children; cur && i < size; cur = cur->next->next, i++) |
| 784 | { | 823 | { |
| 785 | idx1 = *(uint64_t *) (g_hash_table_lookup(ref_table, cur)); | 824 | idx1 = *(uint64_t *) (g_hash_table_lookup(ref_table, cur)); |
| 825 | #if G_BYTE_ORDER == G_BIG_ENDIAN | ||
| 826 | idx1 = idx1 << ((sizeof(uint64_t) - dict_param_size) * 8); | ||
| 827 | #endif | ||
| 786 | memcpy(buff + i * dict_param_size, &idx1, dict_param_size); | 828 | memcpy(buff + i * dict_param_size, &idx1, dict_param_size); |
| 787 | byte_convert(buff + i * dict_param_size, dict_param_size); | 829 | byte_convert(buff + i * dict_param_size, dict_param_size); |
| 788 | 830 | ||
| 789 | idx2 = *(uint64_t *) (g_hash_table_lookup(ref_table, cur->next)); | 831 | idx2 = *(uint64_t *) (g_hash_table_lookup(ref_table, cur->next)); |
| 832 | #if G_BYTE_ORDER == G_BIG_ENDIAN | ||
| 833 | idx2 = idx2 << ((sizeof(uint64_t) - dict_param_size) * 8); | ||
| 834 | #endif | ||
| 790 | memcpy(buff + (i + size) * dict_param_size, &idx2, dict_param_size); | 835 | memcpy(buff + (i + size) * dict_param_size, &idx2, dict_param_size); |
| 791 | byte_convert(buff + (i + size) * dict_param_size, dict_param_size); | 836 | byte_convert(buff + (i + size) * dict_param_size, dict_param_size); |
| 792 | } | 837 | } |
| @@ -916,7 +961,12 @@ void plist_to_bin(plist_t plist, char **plist_bin, uint32_t * length) | |||
| 916 | for (i = 0; i < num_objects; i++) | 961 | for (i = 0; i < num_objects; i++) |
| 917 | { | 962 | { |
| 918 | uint8_t *offsetbuff = (uint8_t *) malloc(offset_size); | 963 | uint8_t *offsetbuff = (uint8_t *) malloc(offset_size); |
| 919 | memcpy(offsetbuff, offsets + i, offset_size); | 964 | |
| 965 | #if G_BYTE_ORDER == G_BIG_ENDIAN | ||
| 966 | offsets[i] = offsets[i] << ((sizeof(uint64_t) - offset_size) * 8); | ||
| 967 | #endif | ||
| 968 | |||
| 969 | memcpy(offsetbuff, &offsets[i], offset_size); | ||
| 920 | byte_convert(offsetbuff, offset_size); | 970 | byte_convert(offsetbuff, offset_size); |
| 921 | g_byte_array_append(bplist_buff, offsetbuff, offset_size); | 971 | g_byte_array_append(bplist_buff, offsetbuff, offset_size); |
| 922 | free(offsetbuff); | 972 | free(offsetbuff); |
