diff --git a/core/include/byteorder.h b/core/include/byteorder.h index 3e018897e6..61d8ebd39a 100644 --- a/core/include/byteorder.h +++ b/core/include/byteorder.h @@ -251,6 +251,19 @@ static inline uint16_t byteorder_bebuftohs(const uint8_t *buf); */ static inline uint32_t byteorder_bebuftohl(const uint8_t *buf); +/** + * @brief Read a big endian encoded unsigned integer from a buffer + * into host byte order encoded variable, 64-bit + * + * @note This function is agnostic to the alignment of the target + * value in the given buffer + * + * @param[in] buf position in a buffer holding the target value + * + * @return 64-bit unsigned integer in host byte order + */ +static inline uint64_t byteorder_bebuftohll(const uint8_t *buf); + /** * @brief Write a host byte order encoded unsigned integer as big * endian encoded value into a buffer, 16-bit @@ -275,6 +288,18 @@ static inline void byteorder_htobebufs(uint8_t *buf, uint16_t val); */ static inline void byteorder_htobebufl(uint8_t *buf, uint32_t val); +/** + * @brief Write a host byte order encoded unsigned integer as big + * endian encoded value into a buffer, 64-bit + * + * @note This function is alignment agnostic and works with any given + * memory location of the buffer + * + * @param[out] buf target buffer, must be able to accept 8 bytes + * @param[in] val value written to the buffer, in host byte order + */ +static inline void byteorder_htobebufll(uint8_t *buf, uint64_t val); + /** * @brief Convert from host byte order to network byte order, 16 bit. * @see byteorder_htons() @@ -506,6 +531,24 @@ static inline uint32_t byteorder_bebuftohl(const uint8_t *buf) #endif } +static inline uint64_t byteorder_bebuftohll(const uint8_t *buf) +{ +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + return (((uint64_t) buf[0] << 56) + | ((uint64_t) buf[1] << 48) + | ((uint64_t) buf[2] << 40) + | ((uint64_t) buf[3] << 32) + | ((uint64_t) buf[4] << 24) + | ((uint64_t) buf[5] << 16) + | ((uint64_t) buf[6] << 8) + | ((uint64_t) buf[7] << 0)); +#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + /* big endian to big endian conversion is easy, but buffer might be + * unaligned */ + return unaligned_get_u64(buf); +#endif +} + static inline void byteorder_htobebufs(uint8_t *buf, uint16_t val) { #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ @@ -532,6 +575,24 @@ static inline void byteorder_htobebufl(uint8_t *buf, uint32_t val) #endif } +static inline void byteorder_htobebufll(uint8_t *buf, uint64_t val) +{ +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + buf[0] = (uint8_t)(val >> 56); + buf[1] = (uint8_t)(val >> 48); + buf[2] = (uint8_t)(val >> 40); + buf[3] = (uint8_t)(val >> 32); + buf[4] = (uint8_t)(val >> 24); + buf[5] = (uint8_t)(val >> 16); + buf[6] = (uint8_t)(val >> 8); + buf[7] = (uint8_t)(val >> 0); +#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + /* big endian to big endian conversion is easy, but buffer might be + * unaligned */ + memcpy(buf, &val, sizeof(val)); +#endif +} + #ifdef __cplusplus } #endif diff --git a/sys/include/unaligned.h b/sys/include/unaligned.h index ced46ac328..1ea3bce83f 100644 --- a/sys/include/unaligned.h +++ b/sys/include/unaligned.h @@ -53,6 +53,11 @@ typedef struct __attribute__((packed)) { uint32_t val; /**< value */ } uint32_una_t; +/** @brief Unaligned access helper struct (uint64_t version) */ +typedef struct __attribute__((packed)) { + uint64_t val; /**< value */ +} uint64_una_t; + /** * @brief Get uint16_t from possibly unaligned pointer * @@ -79,6 +84,19 @@ static inline uint32_t unaligned_get_u32(const void *ptr) return tmp->val; } +/** + * @brief Get uint64_t from possibly unaligned pointer + * + * @param[in] ptr pointer to read from + * + * @returns value read from @p ptr + */ +static inline uint64_t unaligned_get_u64(const void *ptr) +{ + const uint64_una_t *tmp = (const uint64_una_t *)ptr; + return tmp->val; +} + #ifdef __cplusplus } #endif