Line data Source code
1 : #ifndef AWS_COMMON_BYTE_ORDER_INL
2 : #define AWS_COMMON_BYTE_ORDER_INL
3 :
4 : /**
5 : * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
6 : * SPDX-License-Identifier: Apache-2.0.
7 : */
8 :
9 : #include <aws/common/byte_order.h>
10 : #include <aws/common/common.h>
11 :
12 : #ifdef _WIN32
13 : # include <stdlib.h>
14 : #else
15 : # include <netinet/in.h>
16 : #endif /* _MSC_VER */
17 :
18 : AWS_EXTERN_C_BEGIN
19 :
20 : /**
21 : * Returns 1 if machine is big endian, 0 if little endian.
22 : * If you compile with even -O1 optimization, this check is completely optimized
23 : * out at compile time and code which calls "if (aws_is_big_endian())" will do
24 : * the right thing without branching.
25 : */
26 111236 : AWS_STATIC_IMPL int aws_is_big_endian(void) {
27 111236 : const uint16_t z = 0x100;
28 111236 : return *(const uint8_t *)&z;
29 111236 : }
30 :
31 : /**
32 : * Convert 64 bit integer from host to network byte order.
33 : */
34 111236 : AWS_STATIC_IMPL uint64_t aws_hton64(uint64_t x) {
35 111236 : if (aws_is_big_endian()) {
36 0 : return x;
37 0 : }
38 111236 : #if defined(__x86_64__) && (defined(__GNUC__) || defined(__clang__)) && !defined(CBMC)
39 111236 : uint64_t v;
40 111236 : __asm__("bswap %q0" : "=r"(v) : "0"(x));
41 111236 : return v;
42 0 : #elif defined(_MSC_VER)
43 0 : return _byteswap_uint64(x);
44 0 : #else
45 0 : uint32_t low = x & UINT32_MAX;
46 0 : uint32_t high = (uint32_t)(x >> 32);
47 0 : return ((uint64_t)htonl(low)) << 32 | htonl(high);
48 0 : #endif
49 0 : }
50 :
51 : /**
52 : * Convert 64 bit integer from network to host byte order.
53 : */
54 55918 : AWS_STATIC_IMPL uint64_t aws_ntoh64(uint64_t x) {
55 55918 : return aws_hton64(x);
56 55918 : }
57 :
58 : /**
59 : * Convert 32 bit integer from host to network byte order.
60 : */
61 53153 : AWS_STATIC_IMPL uint32_t aws_hton32(uint32_t x) {
62 0 : #ifdef _WIN32
63 0 : return aws_is_big_endian() ? x : _byteswap_ulong(x);
64 0 : #else
65 0 : return htonl(x);
66 53153 : #endif
67 53153 : }
68 :
69 : /**
70 : * Convert 32 bit float from host to network byte order.
71 : */
72 0 : AWS_STATIC_IMPL float aws_htonf32(float x) {
73 0 : if (aws_is_big_endian()) {
74 0 : return x;
75 0 : }
76 0 :
77 0 : uint8_t *f_storage = (uint8_t *)&x;
78 0 :
79 0 : float ret_value;
80 0 : uint8_t *ret_storage = (uint8_t *)&ret_value;
81 0 :
82 0 : ret_storage[0] = f_storage[3];
83 0 : ret_storage[1] = f_storage[2];
84 0 : ret_storage[2] = f_storage[1];
85 0 : ret_storage[3] = f_storage[0];
86 0 :
87 0 : return ret_value;
88 0 : }
89 :
90 : /**
91 : * Convert 64 bit double from host to network byte order.
92 : */
93 0 : AWS_STATIC_IMPL double aws_htonf64(double x) {
94 0 : if (aws_is_big_endian()) {
95 0 : return x;
96 0 : }
97 0 :
98 0 : uint8_t *f_storage = (uint8_t *)&x;
99 0 :
100 0 : double ret_value;
101 0 : uint8_t *ret_storage = (uint8_t *)&ret_value;
102 0 :
103 0 : ret_storage[0] = f_storage[7];
104 0 : ret_storage[1] = f_storage[6];
105 0 : ret_storage[2] = f_storage[5];
106 0 : ret_storage[3] = f_storage[4];
107 0 : ret_storage[4] = f_storage[3];
108 0 : ret_storage[5] = f_storage[2];
109 0 : ret_storage[6] = f_storage[1];
110 0 : ret_storage[7] = f_storage[0];
111 0 :
112 0 : return ret_value;
113 0 : }
114 :
115 : /**
116 : * Convert 32 bit integer from network to host byte order.
117 : */
118 72396 : AWS_STATIC_IMPL uint32_t aws_ntoh32(uint32_t x) {
119 0 : #ifdef _WIN32
120 0 : return aws_is_big_endian() ? x : _byteswap_ulong(x);
121 0 : #else
122 0 : return ntohl(x);
123 72396 : #endif
124 72396 : }
125 :
126 : /**
127 : * Convert 32 bit float from network to host byte order.
128 : */
129 0 : AWS_STATIC_IMPL float aws_ntohf32(float x) {
130 0 : return aws_htonf32(x);
131 0 : }
132 :
133 : /**
134 : * Convert 32 bit float from network to host byte order.
135 : */
136 0 : AWS_STATIC_IMPL double aws_ntohf64(double x) {
137 0 : return aws_htonf64(x);
138 0 : }
139 :
140 : /**
141 : * Convert 16 bit integer from host to network byte order.
142 : */
143 58165 : AWS_STATIC_IMPL uint16_t aws_hton16(uint16_t x) {
144 0 : #ifdef _WIN32
145 0 : return aws_is_big_endian() ? x : _byteswap_ushort(x);
146 0 : #else
147 0 : return htons(x);
148 58165 : #endif
149 58165 : }
150 :
151 : /**
152 : * Convert 16 bit integer from network to host byte order.
153 : */
154 75814 : AWS_STATIC_IMPL uint16_t aws_ntoh16(uint16_t x) {
155 0 : #ifdef _WIN32
156 0 : return aws_is_big_endian() ? x : _byteswap_ushort(x);
157 0 : #else
158 0 : return ntohs(x);
159 75814 : #endif
160 75814 : }
161 :
162 : AWS_EXTERN_C_END
163 :
164 : #endif /* AWS_COMMON_BYTE_ORDER_INL */
|