191 lines
4.4 KiB
C++
191 lines
4.4 KiB
C++
|
/*
|
||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||
|
*
|
||
|
* This file is part of zmqpp.
|
||
|
* Copyright (c) 2011-2015 Contributors as noted in the AUTHORS file.
|
||
|
*/
|
||
|
|
||
|
/**
|
||
|
* \file
|
||
|
*
|
||
|
* \date 10 Aug 2011
|
||
|
* \author Ben Gray (\@benjamg)
|
||
|
*/
|
||
|
|
||
|
#ifndef ZMQPP_INET_HPP_
|
||
|
#define ZMQPP_INET_HPP_
|
||
|
|
||
|
#include <utility>
|
||
|
#include <cassert>
|
||
|
#include <cstdint>
|
||
|
|
||
|
/** \todo cross-platform version of including headers. */
|
||
|
// We get htons and htonl from here
|
||
|
#ifdef _WIN32
|
||
|
#include <WinSock2.h>
|
||
|
#else
|
||
|
#include <netinet/in.h>
|
||
|
#endif
|
||
|
|
||
|
#include "compatibility.hpp"
|
||
|
|
||
|
namespace zmqpp
|
||
|
{
|
||
|
|
||
|
/*!
|
||
|
* \brief Possible byte order types.
|
||
|
*
|
||
|
* An enumeration of all the known order types, all two of them.
|
||
|
* There is also an entry for unknown which is just used as a default.
|
||
|
*/
|
||
|
ZMQPP_COMPARABLE_ENUM order {
|
||
|
big_endian, /*!< byte order is big endian */
|
||
|
little_endian /*!< byte order is little endian */
|
||
|
};
|
||
|
|
||
|
/*!
|
||
|
* Common code for the 64bit versions of htons/htons and ntohs/ntohl
|
||
|
*
|
||
|
* As htons and ntohs (or htonl and ntohs) always just do the same thing, ie
|
||
|
* swap bytes if the host order differs from network order or otherwise don't
|
||
|
* do anything, it seemed silly to type the code twice.
|
||
|
*
|
||
|
* \note This code assumes network order is always big endian. Which it is.
|
||
|
* \note The host endian is only checked once and afterwards assumed to remain
|
||
|
* the same.
|
||
|
*
|
||
|
* \param value_to_check unsigned 64 bit integer to swap
|
||
|
* \return swapped (or not) unsigned 64 bit integer
|
||
|
*/
|
||
|
inline uint64_t swap_if_needed(uint64_t const value_to_check)
|
||
|
{
|
||
|
static order host_order = (htonl(42) == 42) ? order::big_endian : order::little_endian;
|
||
|
|
||
|
if (order::big_endian == host_order)
|
||
|
{
|
||
|
return value_to_check;
|
||
|
}
|
||
|
|
||
|
union {
|
||
|
uint64_t integer;
|
||
|
uint8_t bytes[8];
|
||
|
} value { value_to_check };
|
||
|
|
||
|
std::swap(value.bytes[0], value.bytes[7]);
|
||
|
std::swap(value.bytes[1], value.bytes[6]);
|
||
|
std::swap(value.bytes[2], value.bytes[5]);
|
||
|
std::swap(value.bytes[3], value.bytes[4]);
|
||
|
|
||
|
return value.integer;
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
* 64 bit version of the htons/htonl
|
||
|
*
|
||
|
* I've used the name htonll to try and keep with the htonl naming scheme.
|
||
|
* We do not define this function if the macro `htonll` exists.
|
||
|
*
|
||
|
* \param hostlonglong unsigned 64 bit host order integer
|
||
|
* \return unsigned 64 bit network order integer
|
||
|
*/
|
||
|
#ifndef htonll
|
||
|
inline uint64_t htonll(uint64_t const hostlonglong)
|
||
|
{
|
||
|
return zmqpp::swap_if_needed(hostlonglong);
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
/*!
|
||
|
* 64 bit version of the ntohs/ntohl
|
||
|
*
|
||
|
* I've used the name htonll to try and keep with the htonl naming scheme.
|
||
|
* We do not define this function if the macro `ntohll` exists.
|
||
|
*
|
||
|
* \param networklonglong unsigned 64 bit network order integer
|
||
|
* \return unsigned 64 bit host order integer
|
||
|
*/
|
||
|
#ifndef ntohll
|
||
|
inline uint64_t ntohll(uint64_t const networklonglong)
|
||
|
{
|
||
|
return zmqpp::swap_if_needed(networklonglong);
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
/*!
|
||
|
* floating point version of the htons/htonl
|
||
|
*
|
||
|
* \param value host order floating point
|
||
|
* \returns network order floating point
|
||
|
*/
|
||
|
inline float htonf(float value)
|
||
|
{
|
||
|
assert(sizeof(float) == sizeof(uint32_t));
|
||
|
|
||
|
uint32_t temp;
|
||
|
memcpy(&temp, &value, sizeof(uint32_t));
|
||
|
temp = htonl( temp );
|
||
|
memcpy(&value, &temp, sizeof(uint32_t));
|
||
|
|
||
|
return value;
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
* floating point version of the ntohs/ntohl
|
||
|
*
|
||
|
* \param value network order float
|
||
|
* \returns host order float
|
||
|
*/
|
||
|
inline float ntohf(float value)
|
||
|
{
|
||
|
assert(sizeof(float) == sizeof(uint32_t));
|
||
|
|
||
|
uint32_t temp;
|
||
|
memcpy(&temp, &value, sizeof(uint32_t));
|
||
|
temp = ntohl( temp );
|
||
|
memcpy(&value, &temp, sizeof(uint32_t));
|
||
|
|
||
|
return value;
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
* double precision floating point version of the htons/htonl
|
||
|
*
|
||
|
* \param value host order double precision floating point
|
||
|
* \returns network order double precision floating point
|
||
|
*/
|
||
|
inline double htond(double value)
|
||
|
{
|
||
|
assert(sizeof(double) == sizeof(uint64_t));
|
||
|
|
||
|
uint64_t temp;
|
||
|
memcpy(&temp, &value, sizeof(uint64_t));
|
||
|
temp = htonll(temp);
|
||
|
memcpy(&value, &temp, sizeof(uint64_t));
|
||
|
|
||
|
return value;
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
* double precision floating point version of the ntohs/ntohl
|
||
|
*
|
||
|
* \param value network order double precision floating point
|
||
|
* \returns host order double precision floating point
|
||
|
*/
|
||
|
inline double ntohd(double value)
|
||
|
{
|
||
|
assert(sizeof(double) == sizeof(uint64_t));
|
||
|
|
||
|
uint64_t temp;
|
||
|
memcpy(&temp, &value, sizeof(uint64_t));
|
||
|
temp = ntohll(temp);
|
||
|
memcpy(&value, &temp, sizeof(uint64_t));
|
||
|
|
||
|
return value;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
#endif /* INET_HPP_ */
|