blob: 16a5184a7571a7a09910a9f899c45c0248735b07 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef BYTEORDER_H_INCLUDED
#define BYTEORDER_H_INCLUDED
#include <stddef.h>
#include <stdint.h>
#include <algorithm>
#include <boost/detail/endian.hpp>
#include "RocketMQClient.h"
#include "UtilAll.h"
//==============================================================================
/** Contains static methods for converting the byte order between different
endiannesses.
*/
namespace rocketmq {
class ROCKETMQCLIENT_API ByteOrder {
public:
//==============================================================================
/** Swaps the upper and lower bytes of a 16-bit integer. */
static uint16 swap(uint16 value);
/** Reverses the order of the 4 bytes in a 32-bit integer. */
static uint32 swap(uint32 value);
/** Reverses the order of the 8 bytes in a 64-bit integer. */
static uint64 swap(uint64 value);
//==============================================================================
/** Swaps the byte order of a 16-bit int if the CPU is big-endian */
static uint16 swapIfBigEndian(uint16 value);
/** Swaps the byte order of a 32-bit int if the CPU is big-endian */
static uint32 swapIfBigEndian(uint32 value);
/** Swaps the byte order of a 64-bit int if the CPU is big-endian */
static uint64 swapIfBigEndian(uint64 value);
/** Swaps the byte order of a 16-bit int if the CPU is little-endian */
static uint16 swapIfLittleEndian(uint16 value);
/** Swaps the byte order of a 32-bit int if the CPU is little-endian */
static uint32 swapIfLittleEndian(uint32 value);
/** Swaps the byte order of a 64-bit int if the CPU is little-endian */
static uint64 swapIfLittleEndian(uint64 value);
//==============================================================================
/** Turns 4 bytes into a little-endian integer. */
static uint32 littleEndianInt(const void* bytes);
/** Turns 8 bytes into a little-endian integer. */
static uint64 littleEndianInt64(const void* bytes);
/** Turns 2 bytes into a little-endian integer. */
static uint16 littleEndianShort(const void* bytes);
/** Turns 4 bytes into a big-endian integer. */
static uint32 bigEndianInt(const void* bytes);
/** Turns 8 bytes into a big-endian integer. */
static uint64 bigEndianInt64(const void* bytes);
/** Turns 2 bytes into a big-endian integer. */
static uint16 bigEndianShort(const void* bytes);
//==============================================================================
/** Converts 3 little-endian bytes into a signed 24-bit value (which is
* sign-extended to 32 bits). */
static int littleEndian24Bit(const void* bytes);
/** Converts 3 big-endian bytes into a signed 24-bit value (which is
* sign-extended to 32 bits). */
static int bigEndian24Bit(const void* bytes);
/** Copies a 24-bit number to 3 little-endian bytes. */
static void littleEndian24BitToChars(int value, void* destBytes);
/** Copies a 24-bit number to 3 big-endian bytes. */
static void bigEndian24BitToChars(int value, void* destBytes);
//==============================================================================
/** Returns true if the current CPU is big-endian. */
static bool isBigEndian();
};
//==============================================================================
inline uint16 ByteOrder::swap(uint16 n) {
return static_cast<uint16>((n << 8) | (n >> 8));
}
inline uint32 ByteOrder::swap(uint32 n) {
return (n << 24) | (n >> 24) | ((n & 0xff00) << 8) | ((n & 0xff0000) >> 8);
}
inline uint64 ByteOrder::swap(uint64 value) {
return (((uint64)swap((uint32)value)) << 32) | swap((uint32)(value >> 32));
}
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ //__BYTE_ORDER__ is defined by GCC
inline uint16 ByteOrder::swapIfBigEndian(const uint16 v) {
return v;
}
inline uint32 ByteOrder::swapIfBigEndian(const uint32 v) {
return v;
}
inline uint64 ByteOrder::swapIfBigEndian(const uint64 v) {
return v;
}
inline uint16 ByteOrder::swapIfLittleEndian(const uint16 v) {
return swap(v);
}
inline uint32 ByteOrder::swapIfLittleEndian(const uint32 v) {
return swap(v);
}
inline uint64 ByteOrder::swapIfLittleEndian(const uint64 v) {
return swap(v);
}
inline uint32 ByteOrder::littleEndianInt(const void* const bytes) {
return *static_cast<const uint32*>(bytes);
}
inline uint64 ByteOrder::littleEndianInt64(const void* const bytes) {
return *static_cast<const uint64*>(bytes);
}
inline uint16 ByteOrder::littleEndianShort(const void* const bytes) {
return *static_cast<const uint16*>(bytes);
}
inline uint32 ByteOrder::bigEndianInt(const void* const bytes) {
return swap(*static_cast<const uint32*>(bytes));
}
inline uint64 ByteOrder::bigEndianInt64(const void* const bytes) {
return swap(*static_cast<const uint64*>(bytes));
}
inline uint16 ByteOrder::bigEndianShort(const void* const bytes) {
return swap(*static_cast<const uint16*>(bytes));
}
inline bool ByteOrder::isBigEndian() {
return false;
}
#else
inline uint16 ByteOrder::swapIfBigEndian(const uint16 v) {
return swap(v);
}
inline uint32 ByteOrder::swapIfBigEndian(const uint32 v) {
return swap(v);
}
inline uint64 ByteOrder::swapIfBigEndian(const uint64 v) {
return swap(v);
}
inline uint16 ByteOrder::swapIfLittleEndian(const uint16 v) {
return v;
}
inline uint32 ByteOrder::swapIfLittleEndian(const uint32 v) {
return v;
}
inline uint64 ByteOrder::swapIfLittleEndian(const uint64 v) {
return v;
}
inline uint32 ByteOrder::littleEndianInt(const void* const bytes) {
return swap(*static_cast<const uint32*>(bytes));
}
inline uint64 ByteOrder::littleEndianInt64(const void* const bytes) {
return swap(*static_cast<const uint64*>(bytes));
}
inline uint16 ByteOrder::littleEndianShort(const void* const bytes) {
return swap(*static_cast<const uint16*>(bytes));
}
inline uint32 ByteOrder::bigEndianInt(const void* const bytes) {
return *static_cast<const uint32*>(bytes);
}
inline uint64 ByteOrder::bigEndianInt64(const void* const bytes) {
return *static_cast<const uint64*>(bytes);
}
inline uint16 ByteOrder::bigEndianShort(const void* const bytes) {
return *static_cast<const uint16*>(bytes);
}
inline bool ByteOrder::isBigEndian() {
return true;
}
#endif
inline int ByteOrder::littleEndian24Bit(const void* const bytes) {
return (((int)static_cast<const int8*>(bytes)[2]) << 16) | (((int)static_cast<const uint8*>(bytes)[1]) << 8) |
((int)static_cast<const uint8*>(bytes)[0]);
}
inline int ByteOrder::bigEndian24Bit(const void* const bytes) {
return (((int)static_cast<const int8*>(bytes)[0]) << 16) | (((int)static_cast<const uint8*>(bytes)[1]) << 8) |
((int)static_cast<const uint8*>(bytes)[2]);
}
inline void ByteOrder::littleEndian24BitToChars(const int value, void* const destBytes) {
static_cast<uint8*>(destBytes)[0] = (uint8)value;
static_cast<uint8*>(destBytes)[1] = (uint8)(value >> 8);
static_cast<uint8*>(destBytes)[2] = (uint8)(value >> 16);
}
inline void ByteOrder::bigEndian24BitToChars(const int value, void* const destBytes) {
static_cast<uint8*>(destBytes)[0] = (uint8)(value >> 16);
static_cast<uint8*>(destBytes)[1] = (uint8)(value >> 8);
static_cast<uint8*>(destBytes)[2] = (uint8)value;
}
} // namespace rocketmq
#endif // BYTEORDER_H_INCLUDED