1// Copyright 2017 Google Inc. All Rights Reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#ifndef HIGHWAYHASH_ENDIANESS_H_
16#define HIGHWAYHASH_ENDIANESS_H_
17
18// WARNING: this is a "restricted" header because it is included from
19// translation units compiled with different flags. This header and its
20// dependencies must not define any function unless it is static inline and/or
21// within namespace HH_TARGET_NAME. See arch_specific.h for details.
22
23#include <stdint.h>
24
25#if defined(BYTE_ORDER) && defined(LITTLE_ENDIAN) && defined(BIG_ENDIAN)
26
27 /* Someone has already included <endian.h> or equivalent. */
28
29#elif defined(__LITTLE_ENDIAN__)
30
31# define HH_IS_LITTLE_ENDIAN 1
32# define HH_IS_BIG_ENDIAN 0
33# ifdef __BIG_ENDIAN__
34# error "Platform is both little and big endian?"
35# endif
36
37#elif defined(__BIG_ENDIAN__)
38
39# define HH_IS_LITTLE_ENDIAN 0
40# define HH_IS_BIG_ENDIAN 1
41
42#elif defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && \
43 defined(__ORDER_LITTLE_ENDIAN__)
44
45# define HH_IS_LITTLE_ENDIAN (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
46# define HH_IS_BIG_ENDIAN (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
47
48#elif defined(__linux__) || defined(__CYGWIN__) || defined( __GNUC__ ) || \
49 defined( __GNU_LIBRARY__ )
50
51# include <endian.h>
52
53#elif defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__) || \
54 defined(__DragonFly__)
55
56# include <sys/endian.h>
57
58#elif defined(_WIN32)
59
60#define HH_IS_LITTLE_ENDIAN 1
61#define HH_IS_BIG_ENDIAN 0
62
63#else
64
65# error "Unsupported platform. Cannot determine byte order."
66
67#endif
68
69
70#ifndef HH_IS_LITTLE_ENDIAN
71# define HH_IS_LITTLE_ENDIAN (BYTE_ORDER == LITTLE_ENDIAN)
72# define HH_IS_BIG_ENDIAN (BYTE_ORDER == BIG_ENDIAN)
73#endif
74
75
76namespace highwayhash {
77
78#if HH_IS_LITTLE_ENDIAN
79
80static inline uint32_t le32_from_host(uint32_t x) { return x; }
81static inline uint32_t host_from_le32(uint32_t x) { return x; }
82static inline uint64_t le64_from_host(uint64_t x) { return x; }
83static inline uint64_t host_from_le64(uint64_t x) { return x; }
84
85#elif !HH_IS_BIG_ENDIAN
86
87# error "Unsupported byte order."
88
89#elif defined(_WIN16) || defined(_WIN32) || defined(_WIN64)
90
91#include <intrin.h>
92static inline uint32_t host_from_le32(uint32_t x) { return _byteswap_ulong(x); }
93static inline uint32_t le32_from_host(uint32_t x) { return _byteswap_ulong(x); }
94static inline uint64_t host_from_le64(uint64_t x) { return _byteswap_uint64(x);}
95static inline uint64_t le64_from_host(uint64_t x) { return _byteswap_uint64(x);}
96
97#else
98
99static inline uint32_t host_from_le32(uint32_t x) {return __builtin_bswap32(x);}
100static inline uint32_t le32_from_host(uint32_t x) {return __builtin_bswap32(x);}
101static inline uint64_t host_from_le64(uint64_t x) {return __builtin_bswap64(x);}
102static inline uint64_t le64_from_host(uint64_t x) {return __builtin_bswap64(x);}
103
104#endif
105
106} // namespace highwayhash
107
108#endif // HIGHWAYHASH_ENDIANESS_H_
109