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