2019-03-06 20:05:10 +01:00
|
|
|
#ifndef COMPAT_BSWAP_H
|
|
|
|
#define COMPAT_BSWAP_H
|
|
|
|
|
2009-08-18 21:26:55 +02:00
|
|
|
/*
|
|
|
|
* Let's make sure we always have a sane definition for ntohl()/htonl().
|
|
|
|
* Some libraries define those as a function call, just to perform byte
|
|
|
|
* shifting, bringing significant overhead to what should be a simple
|
|
|
|
* operation.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Default version that the compiler ought to optimize properly with
|
|
|
|
* constant values.
|
|
|
|
*/
|
Fix some printf format warnings
commit 51ea551 ("make sure byte swapping is optimal for git"
2009-08-18) introduced a "sane definition for ntohl()/htonl()"
for use on some GNU C platforms. Unfortunately, for some of
these platforms, this results in the introduction of a problem
which is essentially the reverse of a problem that commit 6e1c234
("Fix some warnings (on cygwin) to allow -Werror" 2008-07-3) was
intended to fix.
In particular, on platforms where the uint32_t type is defined
to be unsigned long, the return type of the new ntohl()/htonl()
is causing gcc to issue printf format warnings, such as:
warning: long unsigned int format, unsigned int arg (arg 3)
(nine such warnings, covering six different files). The earlier
commit (6e1c234) needed to suppress these same warnings, except
that the types were in the opposite direction; namely the format
specifier ("%u") was 'unsigned int' and the argument type (ie the
return type of ntohl()) was 'long unsigned int' (aka uint32_t).
In order to suppress these warnings, the earlier commit used the
(C99) PRIu32 format specifier, since the definition of this macro
is suitable for use with the uint32_t type on that platform.
This worked because the return type of the (original) platform
ntohl()/htonl() functions was uint32_t.
In order to suppress these warnings, we change the return type of
the new byte swapping functions in the compat/bswap.h header file
from 'unsigned int' to uint32_t.
Signed-off-by: Ramsay Jones <ramsay@ramsay1.demon.co.uk>
Acked-by: Nicolas Pitre <nico@fluxnic.net>
Signed-off-by: Jeff King <peff@peff.net>
2009-09-30 20:49:24 +02:00
|
|
|
static inline uint32_t default_swab32(uint32_t val)
|
2009-08-18 21:26:55 +02:00
|
|
|
{
|
|
|
|
return (((val & 0xff000000) >> 24) |
|
|
|
|
((val & 0x00ff0000) >> 8) |
|
|
|
|
((val & 0x0000ff00) << 8) |
|
|
|
|
((val & 0x000000ff) << 24));
|
|
|
|
}
|
|
|
|
|
2013-11-14 13:43:36 +01:00
|
|
|
static inline uint64_t default_bswap64(uint64_t val)
|
|
|
|
{
|
|
|
|
return (((val & (uint64_t)0x00000000000000ffULL) << 56) |
|
|
|
|
((val & (uint64_t)0x000000000000ff00ULL) << 40) |
|
|
|
|
((val & (uint64_t)0x0000000000ff0000ULL) << 24) |
|
|
|
|
((val & (uint64_t)0x00000000ff000000ULL) << 8) |
|
|
|
|
((val & (uint64_t)0x000000ff00000000ULL) >> 8) |
|
|
|
|
((val & (uint64_t)0x0000ff0000000000ULL) >> 24) |
|
|
|
|
((val & (uint64_t)0x00ff000000000000ULL) >> 40) |
|
|
|
|
((val & (uint64_t)0xff00000000000000ULL) >> 56));
|
|
|
|
}
|
|
|
|
|
2010-03-29 12:22:19 +02:00
|
|
|
#undef bswap32
|
2013-11-14 13:43:36 +01:00
|
|
|
#undef bswap64
|
2010-03-29 12:22:19 +02:00
|
|
|
|
2009-08-18 21:26:55 +02:00
|
|
|
#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
|
|
|
|
|
2011-03-16 08:00:49 +01:00
|
|
|
#define bswap32 git_bswap32
|
|
|
|
static inline uint32_t git_bswap32(uint32_t x)
|
|
|
|
{
|
|
|
|
uint32_t result;
|
|
|
|
if (__builtin_constant_p(x))
|
|
|
|
result = default_swab32(x);
|
|
|
|
else
|
|
|
|
__asm__("bswap %0" : "=r" (result) : "0" (x));
|
|
|
|
return result;
|
|
|
|
}
|
2009-08-18 21:26:55 +02:00
|
|
|
|
2013-11-14 13:43:36 +01:00
|
|
|
#define bswap64 git_bswap64
|
|
|
|
#if defined(__x86_64__)
|
|
|
|
static inline uint64_t git_bswap64(uint64_t x)
|
|
|
|
{
|
|
|
|
uint64_t result;
|
|
|
|
if (__builtin_constant_p(x))
|
|
|
|
result = default_bswap64(x);
|
|
|
|
else
|
|
|
|
__asm__("bswap %q0" : "=r" (result) : "0" (x));
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
static inline uint64_t git_bswap64(uint64_t x)
|
|
|
|
{
|
|
|
|
union { uint64_t i64; uint32_t i32[2]; } tmp, result;
|
|
|
|
if (__builtin_constant_p(x))
|
|
|
|
result.i64 = default_bswap64(x);
|
|
|
|
else {
|
|
|
|
tmp.i64 = x;
|
|
|
|
result.i32[0] = git_bswap32(tmp.i32[1]);
|
|
|
|
result.i32[1] = git_bswap32(tmp.i32[0]);
|
|
|
|
}
|
|
|
|
return result.i64;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2009-10-19 18:37:05 +02:00
|
|
|
#elif defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64))
|
|
|
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
|
|
|
#define bswap32(x) _byteswap_ulong(x)
|
2013-11-14 13:43:36 +01:00
|
|
|
#define bswap64(x) _byteswap_uint64(x)
|
2009-10-19 18:37:05 +02:00
|
|
|
|
|
|
|
#endif
|
|
|
|
|
2013-11-14 13:43:36 +01:00
|
|
|
#if defined(bswap32)
|
2009-10-19 18:37:05 +02:00
|
|
|
|
2009-08-18 21:26:55 +02:00
|
|
|
#undef ntohl
|
|
|
|
#undef htonl
|
|
|
|
#define ntohl(x) bswap32(x)
|
|
|
|
#define htonl(x) bswap32(x)
|
|
|
|
|
|
|
|
#endif
|
2013-11-14 13:43:36 +01:00
|
|
|
|
|
|
|
#if defined(bswap64)
|
|
|
|
|
|
|
|
#undef ntohll
|
|
|
|
#undef htonll
|
|
|
|
#define ntohll(x) bswap64(x)
|
|
|
|
#define htonll(x) bswap64(x)
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
|
|
|
#undef ntohll
|
|
|
|
#undef htonll
|
|
|
|
|
2014-05-02 21:36:10 +02:00
|
|
|
#if defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && defined(__BIG_ENDIAN)
|
2014-05-02 09:55:29 +02:00
|
|
|
|
|
|
|
# define GIT_BYTE_ORDER __BYTE_ORDER
|
|
|
|
# define GIT_LITTLE_ENDIAN __LITTLE_ENDIAN
|
|
|
|
# define GIT_BIG_ENDIAN __BIG_ENDIAN
|
|
|
|
|
2014-05-02 21:36:10 +02:00
|
|
|
#elif defined(BYTE_ORDER) && defined(LITTLE_ENDIAN) && defined(BIG_ENDIAN)
|
|
|
|
|
|
|
|
# define GIT_BYTE_ORDER BYTE_ORDER
|
|
|
|
# define GIT_LITTLE_ENDIAN LITTLE_ENDIAN
|
|
|
|
# define GIT_BIG_ENDIAN BIG_ENDIAN
|
|
|
|
|
2014-05-02 09:55:29 +02:00
|
|
|
#else
|
|
|
|
|
|
|
|
# define GIT_BIG_ENDIAN 4321
|
|
|
|
# define GIT_LITTLE_ENDIAN 1234
|
|
|
|
|
|
|
|
# if defined(_BIG_ENDIAN) && !defined(_LITTLE_ENDIAN)
|
|
|
|
# define GIT_BYTE_ORDER GIT_BIG_ENDIAN
|
2014-05-30 17:22:40 +02:00
|
|
|
# elif defined(_LITTLE_ENDIAN) && !defined(_BIG_ENDIAN)
|
2014-05-02 09:55:29 +02:00
|
|
|
# define GIT_BYTE_ORDER GIT_LITTLE_ENDIAN
|
2014-10-26 18:34:26 +01:00
|
|
|
# elif defined(__THW_BIG_ENDIAN__) && !defined(__THW_LITTLE_ENDIAN__)
|
|
|
|
# define GIT_BYTE_ORDER GIT_BIG_ENDIAN
|
|
|
|
# elif defined(__THW_LITTLE_ENDIAN__) && !defined(__THW_BIG_ENDIAN__)
|
|
|
|
# define GIT_BYTE_ORDER GIT_LITTLE_ENDIAN
|
2014-05-02 09:55:29 +02:00
|
|
|
# else
|
|
|
|
# error "Cannot determine endianness"
|
2013-11-14 13:43:36 +01:00
|
|
|
# endif
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
2014-05-02 09:55:29 +02:00
|
|
|
#if GIT_BYTE_ORDER == GIT_BIG_ENDIAN
|
2013-11-14 13:43:36 +01:00
|
|
|
# define ntohll(n) (n)
|
|
|
|
# define htonll(n) (n)
|
|
|
|
#else
|
|
|
|
# define ntohll(n) default_bswap64(n)
|
|
|
|
# define htonll(n) default_bswap64(n)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#endif
|
2014-01-23 22:23:09 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Performance might be improved if the CPU architecture is OK with
|
|
|
|
* unaligned 32-bit loads and a fast ntohl() is available.
|
|
|
|
* Otherwise fall back to byte loads and shifts which is portable,
|
|
|
|
* and is faster on architectures with memory alignment issues.
|
|
|
|
*/
|
|
|
|
|
2015-12-29 07:36:00 +01:00
|
|
|
#if !defined(NO_UNALIGNED_LOADS) && ( \
|
|
|
|
defined(__i386__) || defined(__x86_64__) || \
|
2014-01-23 22:23:09 +01:00
|
|
|
defined(_M_IX86) || defined(_M_X64) || \
|
|
|
|
defined(__ppc__) || defined(__ppc64__) || \
|
|
|
|
defined(__powerpc__) || defined(__powerpc64__) || \
|
2015-12-29 07:36:00 +01:00
|
|
|
defined(__s390__) || defined(__s390x__))
|
2014-01-23 22:23:09 +01:00
|
|
|
|
2014-01-23 22:26:42 +01:00
|
|
|
#define get_be16(p) ntohs(*(unsigned short *)(p))
|
2014-01-23 22:23:09 +01:00
|
|
|
#define get_be32(p) ntohl(*(unsigned int *)(p))
|
2017-09-22 18:35:37 +02:00
|
|
|
#define get_be64(p) ntohll(*(uint64_t *)(p))
|
2014-01-23 22:23:09 +01:00
|
|
|
#define put_be32(p, v) do { *(unsigned int *)(p) = htonl(v); } while (0)
|
2017-09-22 18:35:37 +02:00
|
|
|
#define put_be64(p, v) do { *(uint64_t *)(p) = htonll(v); } while (0)
|
2014-01-23 22:23:09 +01:00
|
|
|
|
|
|
|
#else
|
|
|
|
|
2017-07-15 21:22:50 +02:00
|
|
|
static inline uint16_t get_be16(const void *ptr)
|
|
|
|
{
|
|
|
|
const unsigned char *p = ptr;
|
|
|
|
return (uint16_t)p[0] << 8 |
|
|
|
|
(uint16_t)p[1] << 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline uint32_t get_be32(const void *ptr)
|
|
|
|
{
|
|
|
|
const unsigned char *p = ptr;
|
|
|
|
return (uint32_t)p[0] << 24 |
|
|
|
|
(uint32_t)p[1] << 16 |
|
|
|
|
(uint32_t)p[2] << 8 |
|
|
|
|
(uint32_t)p[3] << 0;
|
|
|
|
}
|
|
|
|
|
2017-09-22 18:35:37 +02:00
|
|
|
static inline uint64_t get_be64(const void *ptr)
|
|
|
|
{
|
|
|
|
const unsigned char *p = ptr;
|
|
|
|
return (uint64_t)get_be32(&p[0]) << 32 |
|
|
|
|
(uint64_t)get_be32(&p[4]) << 0;
|
|
|
|
}
|
|
|
|
|
2017-07-15 21:22:50 +02:00
|
|
|
static inline void put_be32(void *ptr, uint32_t value)
|
|
|
|
{
|
|
|
|
unsigned char *p = ptr;
|
|
|
|
p[0] = value >> 24;
|
|
|
|
p[1] = value >> 16;
|
|
|
|
p[2] = value >> 8;
|
|
|
|
p[3] = value >> 0;
|
|
|
|
}
|
2014-01-23 22:23:09 +01:00
|
|
|
|
2017-09-22 18:35:37 +02:00
|
|
|
static inline void put_be64(void *ptr, uint64_t value)
|
|
|
|
{
|
|
|
|
unsigned char *p = ptr;
|
|
|
|
p[0] = value >> 56;
|
|
|
|
p[1] = value >> 48;
|
|
|
|
p[2] = value >> 40;
|
|
|
|
p[3] = value >> 32;
|
|
|
|
p[4] = value >> 24;
|
|
|
|
p[5] = value >> 16;
|
|
|
|
p[6] = value >> 8;
|
|
|
|
p[7] = value >> 0;
|
|
|
|
}
|
|
|
|
|
2014-01-23 22:23:09 +01:00
|
|
|
#endif
|
2019-03-06 20:05:10 +01:00
|
|
|
|
|
|
|
#endif /* COMPAT_BSWAP_H */
|