diff --git a/node/Buffer.hpp b/node/Buffer.hpp index a4921b845..789b835a5 100644 --- a/node/Buffer.hpp +++ b/node/Buffer.hpp @@ -39,7 +39,7 @@ #include "Constants.hpp" #include "Utils.hpp" -#ifdef __GNUC__ +#if defined(__GNUC__) && (!defined(ZT_NO_TYPE_PUNNING)) #define ZT_VAR_MAY_ALIAS __attribute__((__may_alias__)) #else #define ZT_VAR_MAY_ALIAS @@ -204,15 +204,19 @@ public: { if ((i + sizeof(T)) > _l) throw std::out_of_range("Buffer: setAt() beyond end of data"); +#ifdef ZT_NO_TYPE_PUNNING + uint8_t *p = reinterpret_cast<uint8_t *>(_b + i); + for(unsigned int x=1;x<=sizeof(T);++x) + *(p++) = (uint8_t)(v >> (8 * (sizeof(T) - x))); +#else T *const ZT_VAR_MAY_ALIAS p = reinterpret_cast<T *>(_b + i); *p = Utils::hton(v); +#endif } /** * Get a primitive integer value at a given position * - * This behaves like set() in reverse. - * * @param i Index to get integer * @tparam T Integer type (e.g. uint16_t, int64_t) * @return Integer value @@ -223,8 +227,18 @@ public: { if ((i + sizeof(T)) > _l) throw std::out_of_range("Buffer: at() beyond end of data"); +#ifdef ZT_NO_TYPE_PUNNING + T v = 0; + const uint8_t *p = reinterpret_cast<const uint8_t *>(_b + i); + for(unsigned int x=0;x<sizeof(T);++x) { + v <<= 8; + v |= (T)*(p++); + } + return v; +#else const T *const ZT_VAR_MAY_ALIAS p = reinterpret_cast<const T *>(_b + i); return Utils::ntoh(*p); +#endif } /** @@ -240,8 +254,14 @@ public: { if ((_l + sizeof(T)) > C) throw std::out_of_range("Buffer: append beyond capacity"); +#ifdef ZT_NO_TYPE_PUNNING + uint8_t *p = reinterpret_cast<uint8_t *>(_b + _l); + for(unsigned int x=1;x<=sizeof(T);++x) + *(p++) = (uint8_t)(v >> (8 * (sizeof(T) - x))); +#else T *const ZT_VAR_MAY_ALIAS p = reinterpret_cast<T *>(_b + _l); *p = Utils::hton(v); +#endif _l += sizeof(T); } diff --git a/node/Salsa20.cpp b/node/Salsa20.cpp index ae8e18023..de8f1569f 100644 --- a/node/Salsa20.cpp +++ b/node/Salsa20.cpp @@ -19,13 +19,15 @@ #if __BYTE_ORDER == __LITTLE_ENDIAN -// Slow version that does not use type punning -//#define U8TO32_LITTLE(p) ( ((uint32_t)(p)[0]) | ((uint32_t)(p)[1] << 8) | ((uint32_t)(p)[2] << 16) | ((uint32_t)(p)[3] << 24) ) -//static inline void U32TO8_LITTLE(uint8_t *const c,const uint32_t v) { c[0] = (uint8_t)v; c[1] = (uint8_t)(v >> 8); c[2] = (uint8_t)(v >> 16); c[3] = (uint8_t)(v >> 24); } - +#ifdef ZT_NO_TYPE_PUNNING +// Slower version that does not use type punning +#define U8TO32_LITTLE(p) ( ((uint32_t)(p)[0]) | ((uint32_t)(p)[1] << 8) | ((uint32_t)(p)[2] << 16) | ((uint32_t)(p)[3] << 24) ) +static inline void U32TO8_LITTLE(uint8_t *const c,const uint32_t v) { c[0] = (uint8_t)v; c[1] = (uint8_t)(v >> 8); c[2] = (uint8_t)(v >> 16); c[3] = (uint8_t)(v >> 24); } +#else // Fast version that just does 32-bit load/store #define U8TO32_LITTLE(p) (*((const uint32_t *)((const void *)(p)))) #define U32TO8_LITTLE(c,v) *((uint32_t *)((void *)(c))) = (v) +#endif // ZT_NO_TYPE_PUNNING #else // __BYTE_ORDER == __BIG_ENDIAN (we don't support anything else... does MIDDLE_ENDIAN even still exist?)