2

I'm writing a small program that will save and load data, it'll be command line (and not interactive) so there's no point in including libraries I need not include.

When using sockets directly, I get the ntohl functions just by including sockets, however here I don't need sockets. I'm not using wxWidgets, so I don't get to use its byte ordering functions.

In C++ there are lot of new standardised things, for example look at timers and regex (although that's not yet fully supported) but certainly timers!

Is there a standardised way to convert things to network-byte ordered?

Naturally I've tried searching "c++ network byte order cppreference" and similar things, nothing comes up.

BTW in this little project, the program will manipulate files that may be shared across computers, it'd be wrong to assume "always x86_64"

Alec Teal
  • 5,770
  • 3
  • 23
  • 50

5 Answers5

0

Is there a standardised way to convert things to network-byte ordered?

No. There isn't.

Boost ASIO has equivalents, but that somewhat violates your requirements.

Community
  • 1
  • 1
Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
0

There are no C++ standard functions for that, but you can compose the required functionality from the C++ standard functions.

Big-endian-to-host byte-order conversion can be implemented as follows:

#include <boost/detail/endian.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_arithmetic.hpp>
#include <algorithm>

#ifdef BOOST_LITTLE_ENDIAN
#   define BE_TO_HOST_COPY std::reverse_copy
#elif defined(BOOST_BIG_ENDIAN)
#   define BE_TO_HOST_COPY std::copy
#endif

inline void be_to_host(void* dst, void const* src, size_t n) {
    char const* csrc = static_cast<char const*>(src);
    BE_TO_HOST_COPY(csrc, csrc + n, static_cast<char*>(dst));
}

template<class T>
typename boost::enable_if<boost::is_integral<T>, T>::type
be_to_host(T const& big_endian) {
    T host;
    be_to_host(&host, &big_endian, sizeof(T));
    return host;
}

Host-to-big-endian byte-order conversion can be implemented in the same manner.

Usage:

uint64_t big_endian_piece_of_data;
uint64_t host_piece_of_data = be_to_host(big_endian_piece_of_data);
Maxim Egorushkin
  • 131,725
  • 17
  • 180
  • 271
0

The following should work correctly on any endian platform

int32_t getPlatformInt(uint8_t* bytes, size_t num)
{
    int32_t ret;
    assert(num == 4);
    ret = bytes[0] << 24;
    ret |= bytes[1] << 16;
    ret |= bytes[2] << 8;
    ret |= bytes[3];
    return ret;

}

You network integer can easily be cast to an array of chars using:

uint8_t* p = reiterpret_cast<uint8_t*>(&network_byte_order_int)
doron
  • 27,972
  • 12
  • 65
  • 103
0

GCC has __BYTE_ORDER__ which is as good as it will get! It's easy to detect if the compiler is GCC and test this macro, or detect if it is Clang and test that, then stick the byte ordering in a config file and use the pre-processor to conditionally compile bits of code.

Alec Teal
  • 5,770
  • 3
  • 23
  • 50
0

The code from Doron that should work on any platform did not work for me on a big-endian system (Power7 CPU architecture).

Using a compiler built_in is much cleaner and worked great for me using gcc on both Windows and *nix (AIX):

uint32_t getPlatformInt(const uint32_t* bytes) 
  {
    uint32_t ret;
    ret = __builtin_bswap32 (*bytes));
    return ret;
  }

See also How can I reorder the bytes of an integer in c?

Community
  • 1
  • 1
LeslieM
  • 2,105
  • 1
  • 17
  • 8