From c8804cbe8eeee88d94ce6f16de3cf3f7df21cdae Mon Sep 17 00:00:00 2001 From: Danny Robson Date: Tue, 21 Jun 2011 23:36:51 +1000 Subject: [PATCH] Added generic hton and ntoh functions --- configure.ac | 4 +++ test/.gitignore | 1 + test/Makefile.am | 5 ++- test/hton.cpp | 26 ++++++++++++++++ types.cpp | 79 ++++++++++++++++++++++++++++++++++++++++++++++++ types.hpp | 8 +++++ 6 files changed, 122 insertions(+), 1 deletion(-) create mode 100644 test/hton.cpp diff --git a/configure.ac b/configure.ac index 7975ff30..94533c33 100644 --- a/configure.ac +++ b/configure.ac @@ -62,6 +62,10 @@ AC_C_CONST AC_C_RESTRICT AC_C_INLINE +## +## Architecture features +AC_C_BIGENDIAN + ## ## stdlib features AC_FUNC_MMAP diff --git a/test/.gitignore b/test/.gitignore index 5a6e99aa..5407c90c 100644 --- a/test/.gitignore +++ b/test/.gitignore @@ -1,5 +1,6 @@ /backtrace /float +/hton /ip /json-check /maths diff --git a/test/Makefile.am b/test/Makefile.am index f641d486..d3887ac0 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -7,7 +7,7 @@ AM_CPPFLAGS = \ AM_LDFLAGS = $(COMMON_LDFLAGS) -TEST_BIN = backtrace float range maths matrix version ip +TEST_BIN = backtrace float range maths matrix version ip hton TESTS = $(TEST_BIN) json.pl check_PROGRAMS = $(TEST_BIN) json-check EXTRA_DIST = json.pl @@ -34,5 +34,8 @@ version_LDADD = $(builddir)/../libutil.la $(BOOST_SYSTEM_LIB) ip_SOURCES = ip.cpp ip_LDADD = $(builddir)/../libutil.la $(BOOST_SYSTEM_LIB) +hton_SOURCES = hton.cpp +hton_LDADD = $(builddir)/../libutil.la $(BOOST_SYSTEM_LIB) + json_check_SOURCES = json-check.cpp json_check_LDADD = $(builddir)/../libutil.la $(BOOST_FILESYSTEM_LIB) diff --git a/test/hton.cpp b/test/hton.cpp new file mode 100644 index 00000000..4bbe6183 --- /dev/null +++ b/test/hton.cpp @@ -0,0 +1,26 @@ + +#include "../types.hpp" + +#include "../debug.hpp" + +#include +#include +#include + +using namespace std; + + +int +main (int argc, char **argv) { + + uint16_t u16 = 0x1358; + uint32_t u32 = 0x12345678; + + check_eq (htons (u16), hton (u16)); + check_eq (htonl (u32), hton (u32)); + + check_eq (ntohs (u16), hton (u16)); + check_eq (ntohl (u32), hton (u32)); + + return EXIT_SUCCESS; +} diff --git a/types.cpp b/types.cpp index 82b72f61..e9c91c8f 100644 --- a/types.cpp +++ b/types.cpp @@ -1,5 +1,7 @@ #include "types.hpp" +#include + using namespace std; @@ -10,3 +12,80 @@ template <> std::string type_to_string (void) { return "const " #T; } do_type_to_string (float) do_type_to_string (double) +#ifdef WORDS_BIGENDIAN +/* Big endian doesn't need swapping */ +template +T hton (T val) { + static_assert (is_fundamental (), "hton implementation assumes fundamental types"); + static_assert (is_unsigned (), "hton implementation does not handle signed"); + return val; +} + +template +T ntoh (T val) { + static_assert (is_fundamental (), "ntoh implementation assumes fundamental types"); + static_assert (is_unsigned (), "ntoh implementation does not handle signed"); + return val; +} + +template <> uint8_t hton ( uint8_t); +template <> uint16_t hton (uint16_t); +template <> uint32_t hton (uint32_t); +template <> uint64_t hton (uint64_t); + +template <> uint8_t ntoh ( uint8_t); +template <> uint16_t ntoh (uint16_t); +template <> uint32_t ntoh (uint32_t); +template <> uint64_t ntoh (uint64_t); + +#else + +static void +byte_swap (uint8_t *restrict dst, uint8_t *restrict src, size_t len) { + for (unsigned int i = 0; i < len; ++i) + dst[len - i - 1] = src[i]; +} + + +template +T +hton (T i) { + // Unsure if this will really be sensible for non-intrinsic types, or types larger than 8 bytes. + static_assert (is_fundamental ::value, "hton implementation assumes fundamental types"); + static_assert (is_unsigned ::value, "hton implementation does not handle signed"); + + T swapped; + byte_swap (reinterpret_cast (&swapped), + reinterpret_cast (&i), + sizeof (T)); + return swapped; +} + + +template +T +ntoh (T i) { + // Unsure if this will really be sensible for non-intrinsic types, or types larger than 8 bytes. + static_assert (is_fundamental ::value, "ntoh implementation assumes fundamental types"); + static_assert (is_unsigned ::value, "ntoh implementation does not handle signed"); + + T swapped; + byte_swap (reinterpret_cast (&swapped), + reinterpret_cast (&i), + sizeof (T)); + return swapped; +} + +template <> uint8_t hton (uint8_t i) { return i; } +template <> uint8_t ntoh (uint8_t i) { return i; } + +template uint16_t ntoh (uint16_t); +template uint32_t ntoh (uint32_t); +template uint64_t ntoh (uint64_t); + +template uint16_t hton (uint16_t); +template uint32_t hton (uint32_t); +template uint64_t hton (uint64_t); + +#endif + diff --git a/types.hpp b/types.hpp index dbbd9922..e9c5691a 100644 --- a/types.hpp +++ b/types.hpp @@ -97,4 +97,12 @@ template size_t elems(T (&)[N]) { return N; } + +template +T hton (T); + + +template +T ntoh (T); + #endif // __TYPES_HPP