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..b73df5f6 --- /dev/null +++ b/libs/net/test/endian.cpp @@ -0,0 +1,49 @@ +/*============================================================================= + 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 + +namespace testspr { + static void endian_test() { + using namespace sprout; + + { // 16 + TESTSPR_ASSERT(sprout::net::detail::reverse(uint16_t(0x0A1B)) == uint16_t(0x1B0A)); + TESTSPR_ASSERT(sprout::net::detail::reverse(uint16_t(0x1B0A)) == uint16_t(0x0A1B)); + TESTSPR_ASSERT(sprout::net::detail::reverse_words(uint16_t(0x0A1B)) == uint16_t(0x1B0A)); + TESTSPR_ASSERT(sprout::net::detail::reverse_words(uint16_t(0x1B0A)) == uint16_t(0x0A1B)); + } + + { // 32 + TESTSPR_ASSERT(sprout::net::detail::reverse(uint32_t(0x0A1B2C3D)) == uint32_t(0x3D2C1B0A)); + TESTSPR_ASSERT(sprout::net::detail::reverse(uint32_t(0x3D2C1B0A)) == uint32_t(0x0A1B2C3D)); + TESTSPR_ASSERT(sprout::net::detail::reverse_words(uint32_t(0x0A1B2C3D)) == uint32_t(0x1B0A3D2C)); + TESTSPR_ASSERT(sprout::net::detail::reverse_words(uint32_t(0x1B0A3D2C)) == uint32_t(0x0A1B2C3D)); + } + + { // 64 + TESTSPR_ASSERT(sprout::net::detail::reverse(uint64_t(0x0A1B2C3D4E5F6A7B)) == uint64_t(0x7B6A5F4E3D2C1B0A)); + TESTSPR_ASSERT(sprout::net::detail::reverse(uint64_t(0x7B6A5F4E3D2C1B0A)) == uint64_t(0x0A1B2C3D4E5F6A7B)); + TESTSPR_ASSERT(sprout::net::detail::reverse_words(uint64_t(0x0A1B2C3D4E5F6A7B)) == uint64_t(0x1B0A3D2C5F4E7B6A)); + TESTSPR_ASSERT(sprout::net::detail::reverse_words(uint64_t(0x1B0A3D2C5F4E7B6A)) == uint64_t(0x0A1B2C3D4E5F6A7B)); + } + } +} // 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..5e1d1e6f --- /dev/null +++ b/sprout/net/endian.hpp @@ -0,0 +1,175 @@ +/*============================================================================= + 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 { + /* + * lshift_by + * Left shift 'val' by 'n' bytes + */ + template + SPROUT_CONSTEXPR T lshift_by(T val, uint_fast8_t n) { + return val << (n * 8); + } + + /* + * rshift_by + * Right shift 'val' by 'n' bytes + */ + template + SPROUT_CONSTEXPR T rshift_by(T val, uint_fast8_t n) { + return val >> (n * 8); + } + + /* + * mask_t + * Mask 'n'th byte + */ + template + SPROUT_CONSTEXPR T mask_at(uint_fast8_t n) { + return lshift_by(T(0xFF), n); + } + + /* + * byte_at + * Get 'n'th byte from 'val' + */ + template + SPROUT_CONSTEXPR T byte_at(T val, uint_fast8_t n) { + return rshift_by((val & mask_at(n)), n); + } + + /* + * replace_at + * Replace, in 'val', 'n'th byte with 'byte_val' + */ + template + SPROUT_CONSTEXPR T replace_at(T val, uint8_t byte_val, uint_fast8_t n) { + return (val & ~mask_at(n)) | lshift_by(T(byte_val), n); + } + + /* + * copy + * Copy, in 'val', byte at index 'from' to byte at index 'to' + */ + template + SPROUT_CONSTEXPR T copy(T val, uint_fast8_t from, uint_fast8_t to) { + return replace_at(val, byte_at(val, from), to); + } + + /* + * swap + * Swap, in 'val', byte at index 'n1' with byte at index 'n2' + */ + template + SPROUT_CONSTEXPR T swap(T val, uint_fast8_t n1, uint_fast8_t n2) { + return replace_at(copy(val, n1, n2), byte_at(val, n2), n1); + } + + /* + * reverse_impl + * Swap, in 'val', byte at index 'n1' with byte at index 'n2' in 'val', increment n1, decrement n2 until n1 > n2 + */ + template + SPROUT_CONSTEXPR T reverse_impl(T val, uint_fast8_t n1, uint_fast8_t n2) { + return n1 > n2 ? val : reverse_impl(swap(val, n1, n2), n1 + 1, n2 - 1); + } + + /* + * reverse + * Reverse 'val' + */ + template + SPROUT_CONSTEXPR T reverse(T val) { + return reverse_impl(val, 0, sizeof(T) - 1); + } + + /* + * reverse_words_impl + * Swap, in 'val', byte at index 'n' - 1 with byte at index 'n' - 2, decrement n by 2 until n == 0 + */ + template + SPROUT_CONSTEXPR T reverse_words_impl(T val, uint_fast8_t n) { + return n == 0 ? val : reverse_words_impl(swap(val, n - 1, n - 2), n - 2); + } + + /* + * reverse_words + * Reverse each word in 'val' + */ + template + SPROUT_CONSTEXPR T reverse_words(T val) { + return reverse_words_impl(val, sizeof(T)); + } + } // namespace detail + + // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3620.pdf + // template<> + // constexpr unsigned-integral hton(unsigned-integral host) + 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 + } + + // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3620.pdf + // template<> + // constexpr unsigned-integral ntoh(unsigned-integral net) + 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 + } + + // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3620.pdf + // uint32_t htonl(uint32_t host32) + SPROUT_CONSTEXPR uint32_t htonl(uint32_t host32) { + return hton(host32); + } + + // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3620.pdf + // uint16_t htons(uint16_t host16) + SPROUT_CONSTEXPR uint16_t htons(uint16_t host16) { + return hton(host16); + } + + // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3620.pdf + // uint32_t ntohl(uint32_t net32) + SPROUT_CONSTEXPR uint32_t ntohl(uint32_t net32) { + return ntoh(net32); + } + + // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3620.pdf + // uint16_t ntohs(uint32_t net16) + SPROUT_CONSTEXPR uint16_t ntohs(uint16_t net16) { + return ntoh(net16); + } + } //namespace net +} // namespace sprout + +#endif // #ifndef SPROUT_NET_NET_HPP