1 ///////////////////////////////////////////////////////////////////////////////
4 /// \brief Reading and writing integers from and to buffers
6 // This code has been put into the public domain.
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 ///////////////////////////////////////////////////////////////////////////////
14 #ifndef LZMA_INTEGER_H
15 #define LZMA_INTEGER_H
17 // I'm aware of AC_CHECK_ALIGNED_ACCESS_REQUIRED from Autoconf archive, but
18 // it's not useful for us. We don't care if unaligned access is supported,
19 // we care if it is fast. Some systems can emulate unaligned access in
20 // software, which is horribly slow; we want to use byte-by-byte access on
21 // such systems but the Autoconf test would detect such a system as
22 // supporting unaligned access.
24 // NOTE: HAVE_FAST_UNALIGNED_ACCESS indicates only support for 16-bit and
25 // 32-bit integer loads and stores. 64-bit integers may or may not work.
26 // That's why 64-bit functions are commented out.
27 #ifdef HAVE_FAST_UNALIGNED_ACCESS
29 // On big endian, we need byte swapping.
31 // TODO: Big endian PowerPC supports byte swapping load and store instructions
32 // that also allow unaligned access. Inline assembler could be OK for that.
33 #ifdef WORDS_BIGENDIAN
35 # define integer_convert_16(n) bswap_16(n)
36 # define integer_convert_32(n) bswap_32(n)
37 # define integer_convert_64(n) bswap_64(n)
39 # define integer_convert_16(n) (n)
40 # define integer_convert_32(n) (n)
41 # define integer_convert_64(n) (n)
45 static inline uint16_t
46 integer_read_16(const uint8_t buf[static 2])
48 uint16_t ret = *(const uint16_t *)(buf);
49 return integer_convert_16(ret);
53 static inline uint32_t
54 integer_read_32(const uint8_t buf[static 4])
56 uint32_t ret = *(const uint32_t *)(buf);
57 return integer_convert_32(ret);
62 static inline uint64_t
63 integer_read_64(const uint8_t buf[static 8])
65 uint64_t ret = *(const uint64_t *)(buf);
66 return integer_convert_64(ret);
72 integer_write_16(uint8_t buf[static 2], uint16_t num)
74 *(uint16_t *)(buf) = integer_convert_16(num);
79 integer_write_32(uint8_t buf[static 4], uint32_t num)
81 *(uint32_t *)(buf) = integer_convert_32(num);
87 integer_write_64(uint8_t buf[static 8], uint64_t num)
89 *(uint64_t *)(buf) = integer_convert_64(num);
96 static inline uint16_t
97 integer_read_16(const uint8_t buf[static 2])
99 uint16_t ret = buf[0] | (buf[1] << 8);
104 static inline uint32_t
105 integer_read_32(const uint8_t buf[static 4])
107 uint32_t ret = buf[0];
108 ret |= (uint32_t)(buf[1]) << 8;
109 ret |= (uint32_t)(buf[2]) << 16;
110 ret |= (uint32_t)(buf[3]) << 24;
116 static inline uint64_t
117 integer_read_64(const uint8_t buf[static 8])
119 uint64_t ret = buf[0];
120 ret |= (uint64_t)(buf[1]) << 8;
121 ret |= (uint64_t)(buf[2]) << 16;
122 ret |= (uint64_t)(buf[3]) << 24;
123 ret |= (uint64_t)(buf[4]) << 32;
124 ret |= (uint64_t)(buf[5]) << 40;
125 ret |= (uint64_t)(buf[6]) << 48;
126 ret |= (uint64_t)(buf[7]) << 56;
133 integer_write_16(uint8_t buf[static 2], uint16_t num)
135 buf[0] = (uint8_t)(num);
136 buf[1] = (uint8_t)(num >> 8);
141 integer_write_32(uint8_t buf[static 4], uint32_t num)
143 buf[0] = (uint8_t)(num);
144 buf[1] = (uint8_t)(num >> 8);
145 buf[2] = (uint8_t)(num >> 16);
146 buf[3] = (uint8_t)(num >> 24);
152 integer_write_64(uint8_t buf[static 8], uint64_t num)
154 buf[0] = (uint8_t)(num);
155 buf[1] = (uint8_t)(num >> 8);
156 buf[2] = (uint8_t)(num >> 16);
157 buf[3] = (uint8_t)(num >> 24);
158 buf[4] = (uint8_t)(num >> 32);
159 buf[5] = (uint8_t)(num >> 40);
160 buf[6] = (uint8_t)(num >> 48);
161 buf[7] = (uint8_t)(num >> 56);