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 18AWS_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 */ 26AWS_STATIC_IMPL int aws_is_big_endian(void) { 27 const uint16_t z = 0x100; 28 return *(const uint8_t *)&z; 29} 30 31/** 32 * Convert 64 bit integer from host to network byte order. 33 */ 34AWS_STATIC_IMPL uint64_t aws_hton64(uint64_t x) { 35 if (aws_is_big_endian()) { 36 return x; 37 } 38#if defined(__x86_64__) && (defined(__GNUC__) || defined(__clang__)) && !defined(CBMC) 39 uint64_t v; 40 __asm__("bswap %q0" : "=r"(v) : "0"(x)); 41 return v; 42#elif defined(_MSC_VER) 43 return _byteswap_uint64(x); 44#else 45 uint32_t low = x & UINT32_MAX; 46 uint32_t high = (uint32_t)(x >> 32); 47 return ((uint64_t)htonl(low)) << 32 | htonl(high); 48#endif 49} 50 51/** 52 * Convert 64 bit integer from network to host byte order. 53 */ 54AWS_STATIC_IMPL uint64_t aws_ntoh64(uint64_t x) { 55 return aws_hton64(x); 56} 57 58/** 59 * Convert 32 bit integer from host to network byte order. 60 */ 61AWS_STATIC_IMPL uint32_t aws_hton32(uint32_t x) { 62#ifdef _WIN32 63 return aws_is_big_endian() ? x : _byteswap_ulong(x); 64#else 65 return htonl(x); 66#endif 67} 68 69/** 70 * Convert 32 bit float from host to network byte order. 71 */ 72AWS_STATIC_IMPL float aws_htonf32(float x) { 73 if (aws_is_big_endian()) { 74 return x; 75 } 76 77 uint8_t *f_storage = (uint8_t *)&x; 78 79 float ret_value; 80 uint8_t *ret_storage = (uint8_t *)&ret_value; 81 82 ret_storage[0] = f_storage[3]; 83 ret_storage[1] = f_storage[2]; 84 ret_storage[2] = f_storage[1]; 85 ret_storage[3] = f_storage[0]; 86 87 return ret_value; 88} 89 90/** 91 * Convert 64 bit double from host to network byte order. 92 */ 93AWS_STATIC_IMPL double aws_htonf64(double x) { 94 if (aws_is_big_endian()) { 95 return x; 96 } 97 98 uint8_t *f_storage = (uint8_t *)&x; 99 100 double ret_value; 101 uint8_t *ret_storage = (uint8_t *)&ret_value; 102 103 ret_storage[0] = f_storage[7]; 104 ret_storage[1] = f_storage[6]; 105 ret_storage[2] = f_storage[5]; 106 ret_storage[3] = f_storage[4]; 107 ret_storage[4] = f_storage[3]; 108 ret_storage[5] = f_storage[2]; 109 ret_storage[6] = f_storage[1]; 110 ret_storage[7] = f_storage[0]; 111 112 return ret_value; 113} 114 115/** 116 * Convert 32 bit integer from network to host byte order. 117 */ 118AWS_STATIC_IMPL uint32_t aws_ntoh32(uint32_t x) { 119#ifdef _WIN32 120 return aws_is_big_endian() ? x : _byteswap_ulong(x); 121#else 122 return ntohl(x); 123#endif 124} 125 126/** 127 * Convert 32 bit float from network to host byte order. 128 */ 129AWS_STATIC_IMPL float aws_ntohf32(float x) { 130 return aws_htonf32(x); 131} 132 133/** 134 * Convert 32 bit float from network to host byte order. 135 */ 136AWS_STATIC_IMPL double aws_ntohf64(double x) { 137 return aws_htonf64(x); 138} 139 140/** 141 * Convert 16 bit integer from host to network byte order. 142 */ 143AWS_STATIC_IMPL uint16_t aws_hton16(uint16_t x) { 144#ifdef _WIN32 145 return aws_is_big_endian() ? x : _byteswap_ushort(x); 146#else 147 return htons(x); 148#endif 149} 150 151/** 152 * Convert 16 bit integer from network to host byte order. 153 */ 154AWS_STATIC_IMPL uint16_t aws_ntoh16(uint16_t x) { 155#ifdef _WIN32 156 return aws_is_big_endian() ? x : _byteswap_ushort(x); 157#else 158 return ntohs(x); 159#endif 160} 161 162AWS_EXTERN_C_END 163 164#endif /* AWS_COMMON_BYTE_ORDER_INL */ 165