/* * 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 #include #include /** \todo cross-platform version of including headers. */ // We get htons and htonl from here #ifdef _WIN32 #include #else #include #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_ */