/* zmemory.h -- Private inline functions used internally in zlib-ng * For conditions of distribution and use, see copyright notice in zlib.h */ #ifndef _ZMEMORY_H #define _ZMEMORY_H #if defined(__GNUC__) && (__GNUC__ >= 4) # define HAVE_MAY_ALIAS #endif static inline uint16_t zng_memread_2(const void *ptr) { #if defined(HAVE_MAY_ALIAS) typedef struct { uint16_t val; } __attribute__ ((__packed__, __may_alias__)) unaligned_uint16_t; return ((const unaligned_uint16_t *)ptr)->val; #else uint16_t val; memcpy(&val, ptr, sizeof(val)); return val; #endif } static inline uint32_t zng_memread_4(const void *ptr) { #if defined(HAVE_MAY_ALIAS) typedef struct { uint32_t val; } __attribute__ ((__packed__, __may_alias__)) unaligned_uint32_t; return ((const unaligned_uint32_t *)ptr)->val; #else uint32_t val; memcpy(&val, ptr, sizeof(val)); return val; #endif } static inline uint64_t zng_memread_8(const void *ptr) { #if defined(HAVE_MAY_ALIAS) typedef struct { uint64_t val; } __attribute__ ((__packed__, __may_alias__)) unaligned_uint64_t; return ((const unaligned_uint64_t *)ptr)->val; #else uint64_t val; memcpy(&val, ptr, sizeof(val)); return val; #endif } static inline void zng_memwrite_2(void *ptr, uint16_t val) { #if defined(HAVE_MAY_ALIAS) typedef struct { uint16_t val; } __attribute__ ((__packed__, __may_alias__)) unaligned_uint16_t; ((unaligned_uint16_t *)ptr)->val = val; #else memcpy(ptr, &val, sizeof(val)); #endif } static inline void zng_memwrite_4(void *ptr, uint32_t val) { #if defined(HAVE_MAY_ALIAS) typedef struct { uint32_t val; } __attribute__ ((__packed__, __may_alias__)) unaligned_uint32_t; ((unaligned_uint32_t *)ptr)->val = val; #else memcpy(ptr, &val, sizeof(val)); #endif } static inline void zng_memwrite_8(void *ptr, uint64_t val) { #if defined(HAVE_MAY_ALIAS) typedef struct { uint64_t val; } __attribute__ ((__packed__, __may_alias__)) unaligned_uint64_t; ((unaligned_uint64_t *)ptr)->val = val; #else memcpy(ptr, &val, sizeof(val)); #endif } /* Use zng_memread_* instead of memcmp to avoid older compilers not converting memcmp calls to unaligned comparisons when unaligned access is supported. Use memcmp only when unaligned support is not available to avoid an extra call to memcpy. */ static inline int32_t zng_memcmp_2(const void *src0, const void *src1) { #if defined(HAVE_MAY_ALIAS) return zng_memread_2(src0) != zng_memread_2(src1); #else return memcmp(src0, src1, 2); #endif } static inline int32_t zng_memcmp_4(const void *src0, const void *src1) { #if defined(HAVE_MAY_ALIAS) return zng_memread_4(src0) != zng_memread_4(src1); #else return memcmp(src0, src1, 4); #endif } static inline int32_t zng_memcmp_8(const void *src0, const void *src1) { #if defined(HAVE_MAY_ALIAS) return zng_memread_8(src0) != zng_memread_8(src1); #else return memcmp(src0, src1, 8); #endif } #endif