/*
    Copyright (C) 2008-2024, Millistream Market Data <support@millistream.com>

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU Lesser General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.

*/

#ifndef _MDF_BYTESWAP_H
#define _MDF_BYTESWAP_H 1

#if defined HAVE_BYTESWAP_H
# include <byteswap.h>
#elif defined HAVE_SYS_BYTEORDER_H
# include <sys/byteorder.h>
#elif defined HAVE_MACHINE_BYTE_ORDER_H
# include <machine/byte_order.h>
#endif

#if defined HAVE_SYS_ENDIAN_H
# include <sys/endian.h>
#elif defined HAVE_MACHINE_ENDIAN_H
# include <machine/endian.h>
#elif defined HAVE_ENDIAN_H
# include <endian.h>
#elif defined _WIN32 || defined _WIN64
# define __ORDER_LITTLE_ENDIAN__ 1234
# define __ORDER_BIG_ENDIAN__ 4321
# define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__
#elif !defined __BYTE_ORDER__ && !defined __BYTE_ORDER
# error "Endianess of the machine could not be determined!"
#endif

#if defined bswap_16
#
#elif defined bswap16
# define bswap_16(x) bswap16(x)
# define bswap_32(x) bswap32(x)
# define bswap_64(x) bswap64(x)
#elif defined BSWAP_16
# define bswap_16(x) BSWAP_16(x)
# define bswap_32(x) BSWAP_32(x)
# define bswap_64(x) BSWAP_64(x)
#elif defined OSSwapConstInt16
# define bswap_16(x) OSSwapConstInt16(x)
# define bswap_32(x) OSSwapConstInt32(x)
# define bswap_64(x) OSSwapConstInt64(x)
#elif defined _WIN32 || defined _WIN64
# define bswap_16(x) _byteswap_ushort(x)
# define bswap_32(x) _byteswap_ulong(x)
# define bswap_64(x) _byteswap_uint64(x)
#elif !defined bswap_16
# define bswap_16(x) \
({ \
	uint16_t __x = (x); \
	((uint16_t)( \
		(((uint16_t)(__x) & (uint16_t)0x00ffU) << 8) | \
		(((uint16_t)(__x) & (uint16_t)0xff00U) >> 8) )); \
})

# define bswap_32(x) \
({ \
	uint32_t __x = (x); \
	((uint32_t)( \
		(((uint32_t)(__x) & (uint32_t)0x000000ffUL) << 24) | \
		(((uint32_t)(__x) & (uint32_t)0x0000ff00UL) <<  8) | \
		(((uint32_t)(__x) & (uint32_t)0x00ff0000UL) >>  8) | \
		(((uint32_t)(__x) & (uint32_t)0xff000000UL) >> 24) )); \
})

# define bswap_64(x) \
({ \
	uint64_t __x = (x); \
	((uint64_t)( \
		(uint64_t)(((uint64_t)(__x) & (uint64_t)0x00000000000000ffULL) << 56) | \
		(uint64_t)(((uint64_t)(__x) & (uint64_t)0x000000000000ff00ULL) << 40) | \
		(uint64_t)(((uint64_t)(__x) & (uint64_t)0x0000000000ff0000ULL) << 24) | \
		(uint64_t)(((uint64_t)(__x) & (uint64_t)0x00000000ff000000ULL) <<  8) | \
		(uint64_t)(((uint64_t)(__x) & (uint64_t)0x000000ff00000000ULL) >>  8) | \
		(uint64_t)(((uint64_t)(__x) & (uint64_t)0x0000ff0000000000ULL) >> 24) | \
		(uint64_t)(((uint64_t)(__x) & (uint64_t)0x00ff000000000000ULL) >> 40) | \
		(uint64_t)(((uint64_t)(__x) & (uint64_t)0xff00000000000000ULL) >> 56) )); \
})
#endif

#if (defined __BYTE_ORDER__ && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) || (defined __BYTE_ORDER && __BYTE_ORDER == __BIG_ENDIAN) || (defined BYTE_ORDER && BYTE_ORDER == BIG_ENDIAN)
# define cpu_to_le16(v) bswap_16(v)
# define cpu_to_le32(v) bswap_32(v)
# define cpu_to_le64(v) bswap_64(v)
# define le16_to_cpu(v) bswap_16(v)
# define le32_to_cpu(v) bswap_32(v)
# define le64_to_cpu(v) bswap_64(v)
#elif (defined __BYTE_ORDER__ && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) || (defined __BYTE_ORDER && __BYTE_ORDER == __LITTLE_ENDIAN) || (defined BYTE_ORDER && BYTE_ORDER == LITTLE_ENDIAN)
# define cpu_to_le16(v) (v)
# define cpu_to_le32(v) (v)
# define cpu_to_le64(v) (v)
# define le16_to_cpu(v) (v)
# define le32_to_cpu(v) (v)
# define le64_to_cpu(v) (v)
#else
# error "Endianess of the machine could not be determined!"
#endif

#endif

