Merge pull request #60 from cjkay-cpp-utils/master

C++14 N3620 proposal implementation (hton, ntoh)
This commit is contained in:
Bolero MURAKAMI 2014-03-26 11:23:13 +09:00
commit 5baa0580d8
6 changed files with 246 additions and 1 deletions

View file

@ -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 )

1
libs/net/CMakeLists.txt Normal file
View file

@ -0,0 +1 @@
subdirs( test )

View file

@ -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 )

49
libs/net/test/endian.cpp Normal file
View file

@ -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 <sprout/net/endian.hpp>
#include <testspr/tools.hpp>
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 <testspr/include_main.hpp>
#endif
#endif // #ifndef SPROUT_LIBS_NET_TEST_ENDIAN_CPP

17
sprout/net.hpp Normal file
View file

@ -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 <sprout/config.hpp>
#include <sprout/net/endian.hpp>
#endif // #ifndef SPROUT_NET_HPP

175
sprout/net/endian.hpp Normal file
View file

@ -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 <cstdint>
#include <sprout/config.hpp>
#include <boost/detail/endian.hpp>
namespace sprout {
namespace net {
namespace detail {
/*
* lshift_by
* Left shift 'val' by 'n' bytes
*/
template<typename T>
SPROUT_CONSTEXPR T lshift_by(T val, uint_fast8_t n) {
return val << (n * 8);
}
/*
* rshift_by
* Right shift 'val' by 'n' bytes
*/
template<typename T>
SPROUT_CONSTEXPR T rshift_by(T val, uint_fast8_t n) {
return val >> (n * 8);
}
/*
* mask_t
* Mask 'n'th byte
*/
template<typename T>
SPROUT_CONSTEXPR T mask_at(uint_fast8_t n) {
return lshift_by(T(0xFF), n);
}
/*
* byte_at
* Get 'n'th byte from 'val'
*/
template<typename T>
SPROUT_CONSTEXPR T byte_at(T val, uint_fast8_t n) {
return rshift_by((val & mask_at<T>(n)), n);
}
/*
* replace_at
* Replace, in 'val', 'n'th byte with 'byte_val'
*/
template<typename T>
SPROUT_CONSTEXPR T replace_at(T val, uint8_t byte_val, uint_fast8_t n) {
return (val & ~mask_at<T>(n)) | lshift_by(T(byte_val), n);
}
/*
* copy
* Copy, in 'val', byte at index 'from' to byte at index 'to'
*/
template<typename T>
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<typename T>
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<typename T>
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<typename T>
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<typename T>
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<typename T>
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<typename T>
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<typename T>
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