#ifndef UC_PACK_H_ #define UC_PACK_H_ #include #ifndef UC_INLINE #ifdef __GNUC__ # ifdef __clang__ # define UC_INLINE inline __attribute__((always_inline)) # else # define UC_INLINE inline __attribute__((always_inline,flatten)) # endif #else # define UC_INLINE inline #endif #endif /** Functions for serializing/de-serializing integers to and from * byte arrays. * These functions are independant of the host endian. Only * thing to care about is the endian format of the data in * the byte array. */ /** Serialize a uint16_t to a byte array in little endian format. * @param v The value to serialize * @param r The byte array to place the integer in. Must be at least of size 2. */ static UC_INLINE void uc_pack_16_le(uint16_t v, uint8_t *r) { r[0] = v; r[1] = v >> 8; } /** De-serialize a uint16_t from a byte array in little endian format. * @param r The byte array to containing the integer in. Must be at least of size 2. * @param return The deserialized integer from the byte array. */ static UC_INLINE uint16_t uc_unpack_16_le(const uint8_t *r) { uint32_t v; v = r[0]; v |= r[1] << 8; return v; } /** Serialize a uint32_t to a 3 byte(24 bits) array in little endian format. * Only the bottom 24 bits of the uint32_t are used. * * @param v The value to serialize * @param r The byte array to place the integer in. Must be at least of size 3. */ static UC_INLINE void uc_pack_24_le(uint32_t v, uint8_t *r) { r[0] = v; r[1] = v >> 8; r[2] = v >> 16; } /** De-serialize a uint32_t from a 3 byte (24 bit) byte array in little endian format. * @param r The byte array to containing the integer in. Must be at least of size 3. * @param return The deserialized integer from the byte array. */ static UC_INLINE uint32_t uc_unpack_24_le(const uint8_t *r) { uint32_t v; v = r[0]; v |= r[1] << 8; v |= r[2] << 16; return v; } /** Serialize a uint32_t to a byte array in little endian format. * @param v The value to serialize * @param r The byte array to place the integer in. Must be at least of size 4. */ static UC_INLINE void uc_pack_32_le(uint32_t v, uint8_t *r) { r[0] = v; r[1] = v >> 8; r[2] = v >> 16; r[3] = v >> 24; } /** De-serialize a uint32_t from a byte array in little endian format. * @param r The byte array to containing the integer in. Must be at least of size 4. * @param return The deserialized integer from the byte array. */ static UC_INLINE uint32_t uc_unpack_32_le(const uint8_t *r) { uint32_t v; v = r[0]; v |= r[1] << 8; v |= r[2] << 16; v |= (uint32_t)r[3] << 24; return v; } /** Serialize a uint64_t to a byte array in little endian format. * @param v The value to serialize * @param r The byte array to place the integer in. Must be at least of size 8 */ static UC_INLINE void uc_pack_64_le(uint64_t v, uint8_t *r) { r[0] = v; r[1] = v >> 8; r[2] = v >> 16; r[3] = v >> 24; r[4] = v >> 32ULL; r[5] = v >> 40ULL; r[6] = v >> 48ULL; r[7] = v >> 56ULL; } /** De-serialize a uint64_t from a byte array in little endian format. * @param r The byte array to containing the integer in. Must be at least of size 8. * @param return The deserialized integer from the byte array */ static UC_INLINE uint64_t uc_unpack_64_le(const uint8_t *r) { uint64_t v; v = r[0]; v |= r[1] << 8; v |= r[2] << 16; v |= (uint32_t)r[3] << 24; v |= (uint64_t)r[4] << 32ULL; v |= (uint64_t)r[5] << 40ULL; v |= (uint64_t)r[6] << 48ULL; v |= (uint64_t)r[7] << 56ULL; return v; } /** Serialize a uint16_t to a byte array in big endian format. * @param v The value to serialize * @param r The byte array to place the integer in. Must be at least of size 2. */ static UC_INLINE void uc_pack_16_be(uint32_t v, uint8_t *r) { r[0] = v >> 8; r[1] = v; } /** De-serialize a uint16_t from a byte array in big endian format. * @param r The byte array to containing the integer in. Must be at least of size 2. * @param return The deserialized integer from the byte array */ static UC_INLINE uint16_t uc_unpack_16_be(const uint8_t *r) { uint16_t v; v = r[0] << 8; v |= r[1]; return v; } /** Serialize a uint32_t to a 3 byte(24 bits) array in big endian format. * Only the bottom 24 bits of the uint32_t are used. * * @param v The value to serialize * @param r The byte array to place the integer in. Must be at least of size 3. */ static UC_INLINE void uc_pack_24_be(uint32_t v, uint8_t *r) { r[0] = v >> 16; r[1] = v >> 8; r[2] = v; } /** De-serialize a uint32_t from a 3 byte (24 bit) byte array in big endian format. * @param r The byte array to containing the integer in. Must be at least of size 3. * @param return The deserialized integer from the byte array. */ static UC_INLINE uint32_t uc_unpack_24_be(const uint8_t *r) { uint32_t v; v = r[0] << 16; v |= r[1] << 8; v |= r[2]; return v; } /** Serialize a uint32_t to a byte array in big endian format. * @param v The value to serialize * @param r The byte array to place the integer in. Must be at least of size 4. */ static UC_INLINE void uc_pack_32_be(uint32_t v, uint8_t *r) { r[0] = v >> 24; r[1] = v >> 16; r[2] = v >> 8; r[3] = v; } /** De-serialize a uint32_t from a byte array in big endian format. * @param r The byte array to containing the integer in. Must be at least of size 4. * @param return The deserialized integer from the byte array */ static UC_INLINE uint32_t uc_unpack_32_be(const uint8_t *r) { uint32_t v; v = (uint32_t)r[0] << 24; v |= r[1] << 16; v |= r[2] << 8; v |= r[3]; return v; } /** Serialize a uint16_t to a byte array in big endian format. * @param v The value to serialize * @param r The byte array to place the integer in. Must be at least of size 8 */ static UC_INLINE void uc_pack_64_be(uint64_t v, uint8_t *r) { r[0] = v >> 56ULL; r[1] = v >> 48ULL; r[2] = v >> 40ULL; r[3] = v >> 32ULL; r[4] = v >> 24; r[5] = v >> 16; r[6] = v >> 8; r[7] = v; } /** De-serialize a uint64_t from a byte array in big endian format. * @param r The byte array to containing the integer in. Must be at least of size 4. * @param return The deserialized integer from the byte array */ static UC_INLINE uint64_t uc_unpack_64_be(const uint8_t *r) { uint64_t v; v = (uint64_t)r[0] << 56ULL; v |= (uint64_t)r[1] << 48ULL; v |= (uint64_t)r[2] << 40ULL; v |= (uint64_t)r[3] << 32ULL; v |= (uint32_t)r[4] << 24; v |= r[5] << 16; v |= r[6] << 8; v |= r[7]; return v; } #undef UC_INLINE #endif