From 634bd89d9eff858c5b3e2072fc7bf9854e93c4c5 Mon Sep 17 00:00:00 2001 From: Chris Kay Date: Mon, 24 Mar 2014 10:20:33 +0000 Subject: [PATCH] Implemented C++1Y proposal N3620 --- libs/CMakeLists.txt | 2 +- libs/net/CMakeLists.txt | 1 + libs/net/test/CMakeLists.txt | 3 + libs/net/test/endian.cpp | 37 +++++++++++ sprout/net.hpp | 17 +++++ sprout/net/endian.hpp | 117 +++++++++++++++++++++++++++++++++++ 6 files changed, 176 insertions(+), 1 deletion(-) create mode 100644 libs/net/CMakeLists.txt create mode 100644 libs/net/test/CMakeLists.txt create mode 100644 libs/net/test/endian.cpp create mode 100644 sprout/net.hpp create mode 100644 sprout/net/endian.hpp diff --git a/libs/CMakeLists.txt b/libs/CMakeLists.txt index e30877cc..388df659 100644 --- a/libs/CMakeLists.txt +++ b/libs/CMakeLists.txt @@ -1,2 +1,2 @@ -subdirs( algorithm array bitset cstring optional random string tuple utility variant weed ) +subdirs( algorithm array bitset cstring net optional random string tuple utility variant weed ) #subdirs( algorithm array bitset cstring optional random ) diff --git a/libs/net/CMakeLists.txt b/libs/net/CMakeLists.txt new file mode 100644 index 00000000..a32dcf20 --- /dev/null +++ b/libs/net/CMakeLists.txt @@ -0,0 +1 @@ +subdirs( test ) diff --git a/libs/net/test/CMakeLists.txt b/libs/net/test/CMakeLists.txt new file mode 100644 index 00000000..e072a131 --- /dev/null +++ b/libs/net/test/CMakeLists.txt @@ -0,0 +1,3 @@ +add_executable( libs_net_test_endian endian.cpp ) +set_target_properties( libs_net_test_endian PROPERTIES OUTPUT_NAME "endian" ) +add_test( libs_net_test_endian endian ) diff --git a/libs/net/test/endian.cpp b/libs/net/test/endian.cpp new file mode 100644 index 00000000..dbb60eae --- /dev/null +++ b/libs/net/test/endian.cpp @@ -0,0 +1,37 @@ +/*============================================================================= + Copyright (c) 2011-2014 Bolero MURAKAMI + https://github.com/bolero-MURAKAMI/Sprout + + Copyright (c) 2014 Chris KAY + https://github.com/cjkay-cpp-utils/Sprout + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +=============================================================================*/ +#ifndef SPROUT_LIBS_NET_TEST_ENDIAN_CPP +#define SPROUT_LIBS_NET_TEST_ENDIAN_CPP + +#include +#include +#include + +namespace testspr { + static void endian_test() { + using namespace sprout; + + { + TESTSPR_ASSERT(sprout::net::detail::reverse(0xDEADBEEF) == 0xEFBEADDE); + TESTSPR_ASSERT(sprout::net::detail::reverse(0xEFBEADDE) == 0xDEADBEEF); + + TESTSPR_ASSERT(sprout::net::detail::reverse_words(0xDEADBEEF) == 0xADDEEFBE); + TESTSPR_ASSERT(sprout::net::detail::reverse_words(0xADDEEFBE) == 0xDEADBEEF); + } + } +} // namespace testspr + +#ifndef TESTSPR_CPP_INCLUDE +# define TESTSPR_TEST_FUNCTION testspr::endian_test +# include +#endif + +#endif // #ifndef SPROUT_LIBS_NET_TEST_ENDIAN_CPP \ No newline at end of file diff --git a/sprout/net.hpp b/sprout/net.hpp new file mode 100644 index 00000000..8775d032 --- /dev/null +++ b/sprout/net.hpp @@ -0,0 +1,17 @@ +/*============================================================================= + Copyright (c) 2011-2014 Bolero MURAKAMI + https://github.com/bolero-MURAKAMI/Sprout + + Copyright (c) 2014 Chris KAY + https://github.com/cjkay-cpp-utils/Sprout + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +=============================================================================*/ +#ifndef SPROUT_NET_HPP +#define SPROUT_NET_HPP + +#include +#include + +#endif // #ifndef SPROUT_NET_HPP diff --git a/sprout/net/endian.hpp b/sprout/net/endian.hpp new file mode 100644 index 00000000..b17bea77 --- /dev/null +++ b/sprout/net/endian.hpp @@ -0,0 +1,117 @@ +/*============================================================================= + Copyright (c) 2011-2014 Bolero MURAKAMI + https://github.com/bolero-MURAKAMI/Sprout + + Copyright (c) 2014 Chris KAY + https://github.com/cjkay-cpp-utils/Sprout + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +=============================================================================*/ +#ifndef SPROUT_NET_NET_HPP +#define SPROUT_NET_NET_HPP + +#include +#include +#include + +namespace sprout { + namespace net { + namespace detail { + template + SPROUT_CONSTEXPR T lshift(T val, uint_fast8_t byte) { + return val << (byte * 8); + } + + template + SPROUT_CONSTEXPR T rshift(T val, uint_fast8_t byte) { + return val >> (byte * 8); + } + + template + SPROUT_CONSTEXPR T mask(uint_fast8_t byte) { + return lshift(T(0xFF), byte); + } + + template + SPROUT_CONSTEXPR T byte_at(T val, uint_fast8_t byte) { + return rshift((val & mask(byte)), byte); + } + + template + SPROUT_CONSTEXPR T overwrite(T val, uint8_t byte_val, uint_fast8_t to) { + return (val & ~mask(to)) | lshift(T(byte_val), to); + } + + template + SPROUT_CONSTEXPR T move(T val, uint_fast8_t from, uint_fast8_t to) { + return overwrite(val, byte_at(val, from), to); + } + + template + SPROUT_CONSTEXPR T swap(T val, uint_fast8_t byte1, uint_fast8_t byte2) { + return overwrite(move(val, byte1, byte2), byte_at(val, byte2), byte1); + } + + template + SPROUT_CONSTEXPR T reverse_impl(T val, uint_fast8_t byte1, uint_fast8_t byte2) { + return byte1 > byte2 ? val : reverse_impl(swap(val, byte1, byte2), byte1 + 1, byte2 - 1); + } + + template + SPROUT_CONSTEXPR T reverse(T val) { + return reverse_impl(val, 0, sizeof(T) - 1); + } + + template + SPROUT_CONSTEXPR T reverse_words_impl(T val, uint_fast8_t byte) { + return byte == 0 ? val : reverse_words_impl(swap(val, byte - 1, byte - 2), byte - 2); + } + + template + SPROUT_CONSTEXPR T reverse_words(T val) { + return reverse_words_impl(val, sizeof(T)); + } + } + + template + SPROUT_CONSTEXPR T hton(T host) { +#if defined(BOOST_BIG_ENDIAN) + return host; +#elif defined(BOOST_LITTLE_ENDIAN) + return detail::reverse(host); +#elif defined(BOOST_PDP_ENDIAN) + return detail::reverse_words(host); +#endif + } + + template + SPROUT_CONSTEXPR T ntoh(T net) { +#if defined(BOOST_BIG_ENDIAN) + return net; +#elif defined(BOOST_LITTLE_ENDIAN) + return detail::reverse(net); +#elif defined(BOOST_PDP_ENDIAN) + return detail::reverse_words(host); +#endif + } + + SPROUT_CONSTEXPR uint32_t htonl(uint32_t host32) { + return hton(host32); + } + + SPROUT_CONSTEXPR uint16_t htons(uint16_t host16) { + return hton(host16); + } + + SPROUT_CONSTEXPR uint32_t ntohl(uint32_t net32) { + return ntoh(net32); + } + + SPROUT_CONSTEXPR uint16_t ntohs(uint16_t net16) { + return ntoh(net16); + } + } //namespace net +} // namespace sprout + +#endif // #ifndef SPROUT_NET_NET_HPP