diff options
author | Daniel Mack <daniel@zonque.org> | 2015-11-16 13:07:12 +0100 |
---|---|---|
committer | Daniel Mack <daniel@zonque.org> | 2015-11-16 15:13:33 +0100 |
commit | 7f034e980de9192d0c7e163de934f19d2f7d3277 (patch) | |
tree | 44d7c9e6c5233ff726bdb965c4ed0396cde65208 | |
parent | ab32771aa0c2c2ab70248e7e0a4be92fd73512ad (diff) |
basic: add unaligned macros for little endian
Also add test code for that.
-rw-r--r-- | src/basic/unaligned.h | 47 | ||||
-rw-r--r-- | src/test/test-unaligned.c | 74 |
2 files changed, 120 insertions, 1 deletions
diff --git a/src/basic/unaligned.h b/src/basic/unaligned.h index d6181dd9a9..a8115eaa1f 100644 --- a/src/basic/unaligned.h +++ b/src/basic/unaligned.h @@ -21,8 +21,11 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ +#include <endian.h> #include <stdint.h> +/* BE */ + static inline uint16_t unaligned_read_be16(const void *_u) { const uint8_t *u = _u; @@ -64,3 +67,47 @@ static inline void unaligned_write_be64(void *_u, uint64_t a) { unaligned_write_be32(u, (uint32_t) (a >> 32)); unaligned_write_be32(u + 4, (uint32_t) a); } + +/* LE */ + +static inline uint16_t unaligned_read_le16(const void *_u) { + const uint8_t *u = _u; + + return (((uint16_t) u[1]) << 8) | + ((uint16_t) u[0]); +} + +static inline uint32_t unaligned_read_le32(const void *_u) { + const uint8_t *u = _u; + + return (((uint32_t) unaligned_read_le16(u + 2)) << 16) | + ((uint32_t) unaligned_read_le16(u)); +} + +static inline uint64_t unaligned_read_le64(const void *_u) { + const uint8_t *u = _u; + + return (((uint64_t) unaligned_read_le32(u + 4)) << 32) | + ((uint64_t) unaligned_read_le32(u)); +} + +static inline void unaligned_write_le16(void *_u, uint16_t a) { + uint8_t *u = _u; + + u[0] = (uint8_t) a; + u[1] = (uint8_t) (a >> 8); +} + +static inline void unaligned_write_le32(void *_u, uint32_t a) { + uint8_t *u = _u; + + unaligned_write_le16(u, (uint16_t) a); + unaligned_write_le16(u + 2, (uint16_t) (a >> 16)); +} + +static inline void unaligned_write_le64(void *_u, uint64_t a) { + uint8_t *u = _u; + + unaligned_write_le32(u, (uint32_t) a); + unaligned_write_le32(u + 4, (uint32_t) (a >> 32)); +} diff --git a/src/test/test-unaligned.c b/src/test/test-unaligned.c index 1754d06b2d..ec52db262c 100644 --- a/src/test/test-unaligned.c +++ b/src/test/test-unaligned.c @@ -26,7 +26,7 @@ static uint8_t data[] = { 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, }; -int main(int argc, const char *argv[]) { +static void test_be(void) { uint8_t scratch[16]; assert_se(unaligned_read_be16(&data[0]) == 0x0001); @@ -91,3 +91,75 @@ int main(int argc, const char *argv[]) { unaligned_write_be64(&scratch[7], 0x0708090a0b0c0d0e); assert_se(memcmp(&scratch[7], &data[7], sizeof(uint64_t)) == 0); } + +static void test_le(void) { + uint8_t scratch[16]; + + assert_se(unaligned_read_le16(&data[0]) == 0x0100); + assert_se(unaligned_read_le16(&data[1]) == 0x0201); + + assert_se(unaligned_read_le32(&data[0]) == 0x03020100); + assert_se(unaligned_read_le32(&data[1]) == 0x04030201); + assert_se(unaligned_read_le32(&data[2]) == 0x05040302); + assert_se(unaligned_read_le32(&data[3]) == 0x06050403); + + assert_se(unaligned_read_le64(&data[0]) == 0x0706050403020100); + assert_se(unaligned_read_le64(&data[1]) == 0x0807060504030201); + assert_se(unaligned_read_le64(&data[2]) == 0x0908070605040302); + assert_se(unaligned_read_le64(&data[3]) == 0x0a09080706050403); + assert_se(unaligned_read_le64(&data[4]) == 0x0b0a090807060504); + assert_se(unaligned_read_le64(&data[5]) == 0x0c0b0a0908070605); + assert_se(unaligned_read_le64(&data[6]) == 0x0d0c0b0a09080706); + assert_se(unaligned_read_le64(&data[7]) == 0x0e0d0c0b0a090807); + + zero(scratch); + unaligned_write_le16(&scratch[0], 0x0100); + assert_se(memcmp(&scratch[0], &data[0], sizeof(uint16_t)) == 0); + zero(scratch); + unaligned_write_le16(&scratch[1], 0x0201); + assert_se(memcmp(&scratch[1], &data[1], sizeof(uint16_t)) == 0); + + zero(scratch); + unaligned_write_le32(&scratch[0], 0x03020100); + + assert_se(memcmp(&scratch[0], &data[0], sizeof(uint32_t)) == 0); + zero(scratch); + unaligned_write_le32(&scratch[1], 0x04030201); + assert_se(memcmp(&scratch[1], &data[1], sizeof(uint32_t)) == 0); + zero(scratch); + unaligned_write_le32(&scratch[2], 0x05040302); + assert_se(memcmp(&scratch[2], &data[2], sizeof(uint32_t)) == 0); + zero(scratch); + unaligned_write_le32(&scratch[3], 0x06050403); + assert_se(memcmp(&scratch[3], &data[3], sizeof(uint32_t)) == 0); + + zero(scratch); + unaligned_write_le64(&scratch[0], 0x0706050403020100); + assert_se(memcmp(&scratch[0], &data[0], sizeof(uint64_t)) == 0); + zero(scratch); + unaligned_write_le64(&scratch[1], 0x0807060504030201); + assert_se(memcmp(&scratch[1], &data[1], sizeof(uint64_t)) == 0); + zero(scratch); + unaligned_write_le64(&scratch[2], 0x0908070605040302); + assert_se(memcmp(&scratch[2], &data[2], sizeof(uint64_t)) == 0); + zero(scratch); + unaligned_write_le64(&scratch[3], 0x0a09080706050403); + assert_se(memcmp(&scratch[3], &data[3], sizeof(uint64_t)) == 0); + zero(scratch); + unaligned_write_le64(&scratch[4], 0x0B0A090807060504); + assert_se(memcmp(&scratch[4], &data[4], sizeof(uint64_t)) == 0); + zero(scratch); + unaligned_write_le64(&scratch[5], 0x0c0b0a0908070605); + assert_se(memcmp(&scratch[5], &data[5], sizeof(uint64_t)) == 0); + zero(scratch); + unaligned_write_le64(&scratch[6], 0x0d0c0b0a09080706); + assert_se(memcmp(&scratch[6], &data[6], sizeof(uint64_t)) == 0); + zero(scratch); + unaligned_write_le64(&scratch[7], 0x0e0d0c0b0a090807); + assert_se(memcmp(&scratch[7], &data[7], sizeof(uint64_t)) == 0); +} + +int main(int argc, const char *argv[]) { + test_be(); + test_le(); +} |