diff --git a/doc/bikeshed.txt b/doc/bikeshed.txt new file mode 100644 index 0000000..891784d --- /dev/null +++ b/doc/bikeshed.txt @@ -0,0 +1,51 @@ +Conversion function naming bikeshed + +return-by-value modify-argument +------------------ --------------- + +reverse_endianness reverse_endianness_in_place <------- + " reverse_endianness_arg + +reverse reverse_in_place +reverse_endian reverse_endian_in_place +endian_reverse endian_reverse_in_place + +swap_endianness swap_endianness_in_place +swap_endian swap_endian_in_place +endian_swap endian_swap_in_place + +flip_endianness flip_endianness_in_place +flip_endian flip_endian_in_place +endian_flip endian_flip_in_place + + +reverse_order reverse_order_in_place + + +Key points: + +* These names are defined in a user namespace as customization points to be found by + ADL, and so cannot depend on the enclosing namespace name to signal readers that they + are related to endianness. +* These functions are rarely called directly by user code, which is more likely to use + the various conditional functions instead. So explicitness is more important than + brevity. + + + + +merriam-webster.com/dictionary + +reverse [1] (adjective): opposite or contrary to a previous or normal condition +reverse [2] (verb) : to change (something) to an opposite state or condition + +swap (verb) : to give something to someone and receive something in return : to trade or exchange (things) + +flip (verb) + +: to turn (something) over by throwing it up in the air with a quick movement + +: to cause (something) to turn or turn over quickly + +: to move (something) with a quick light movement + \ No newline at end of file diff --git a/include/boost/endian/conversion.hpp b/include/boost/endian/conversion.hpp index 3b18fc6..f6e3b98 100644 --- a/include/boost/endian/conversion.hpp +++ b/include/boost/endian/conversion.hpp @@ -82,18 +82,21 @@ namespace endian // Returns: x if native endian order is little, otherwise reverse_endianness(x) // generic conditional reverse byte order - template - Reversible reverse_endianness(Reversible from) BOOST_NOEXCEPT; + template + inline Reversible conditional_reverse(Reversible from) BOOST_NOEXCEPT; + // Returns: If From == To have different values, from. + // Otherwise reverse_endianness(from). + // Remarks: The From == To test, and as a consequence which form the return takes, is + // is determined at compile time. - // runtime byte order determination - inline BOOST_SCOPED_ENUM(order) effective_order(BOOST_SCOPED_ENUM(order) o) BOOST_NOEXCEPT; - // Return: o if o != native, otherwise big or little depending on native ordering - // runtime conditional reverse byte order template - Reversible reverse_endianness(Reversible from, BOOST_SCOPED_ENUM(order) from_order, - BOOST_SCOPED_ENUM(order) to_order) BOOST_NOEXCEPT; + inline Reversible runtime_conditional_reverse(Reversible from, + BOOST_SCOPED_ENUM(order) from_order, BOOST_SCOPED_ENUM(order) to_order) BOOST_NOEXCEPT; + // Returns: from_order == to_order ? from : reverse_endianness(from). + + //------------------------------------------------------------------------------------// + // Q: What happended to bswap, htobe, and the other synonym functions based on names // popularized by BSD, OS X, and Linux? @@ -147,26 +150,27 @@ namespace endian inline void native_to_little_in_place(Reversible& x) BOOST_NOEXCEPT; // Effects: none if native byte-order is little, otherwise reverse_endianness_in_place(x); - // fully generic conditional reverse in place + // generic conditional reverse in place template - void reverse_endianness_in_place(Reversible& x) BOOST_NOEXCEPT; + inline void conditional_reverse_in_place(Reversible& x) BOOST_NOEXCEPT; // runtime reverse in place template - void reverse_endianness_in_place(Reversible& x, BOOST_SCOPED_ENUM(order) from_order, - BOOST_SCOPED_ENUM(order) to_order) BOOST_NOEXCEPT; + inline void runtime_conditional_reverse_in_place(Reversible& x, + BOOST_SCOPED_ENUM(order) from_order, BOOST_SCOPED_ENUM(order) to_order) + BOOST_NOEXCEPT; //----------------------------------- end synopsis -------------------------------------// //--------------------------------------------------------------------------------------// // // -// implementation // +// return-by-value implementation // // // -// -- reverse portable approach suggested by tymofey, with avoidance of // -// undefined behavior as suggested by Giovanni Piero Deretta, and a further // -// refinement suggested by Pyry Jahkola. // -// -- reverse intrinsic approach suggested by reviewers, and by David Stone, // -// who provided his Boost licensed macro implementation (detail/intrinsic.hpp) // +// -- portable approach suggested by tymofey, with avoidance of undefined behavior // +// as suggested by Giovanni Piero Deretta, with a further refinement suggested // +// by Pyry Jahkola. // +// -- intrinsic approach suggested by reviewers, and by David Stone, who provided // +// his Boost licensed macro implementation (detail/intrinsic.hpp) // // // //--------------------------------------------------------------------------------------// @@ -257,9 +261,13 @@ namespace endian namespace detail { // generic reverse function template implementation approach using std::reverse - // suggested by Mathias Gaunard. + // suggested by Mathias Gaunard. Primary motivation for inclusion is to have an + // independent implementation to test against. Secondary motivation is use by + // floating-point reverse_endianness, but that use is likely to be replace by a + // more tailored floating-point algorithm. + template - inline T generic_reverse_endianness(T x) BOOST_NOEXCEPT + inline T std_reverse_endianness(T x) BOOST_NOEXCEPT { T tmp(x); std::reverse( @@ -272,15 +280,17 @@ namespace endian inline float reverse_endianness(float x) BOOST_NOEXCEPT { BOOST_STATIC_ASSERT_MSG(sizeof(float) == sizeof(uint32_t), - "boost::endian only supprts sizeof(float) == 4; please report error to boost mailing list"); - return detail::generic_reverse_endianness(x); + "boost::endian currently supports only sizeof(float) == 4;" + " please report static_assert failure to the boost mailing list"); + return detail::std_reverse_endianness(x); } inline double reverse_endianness(double x) BOOST_NOEXCEPT { BOOST_STATIC_ASSERT_MSG(sizeof(double) == sizeof(uint64_t), - "boost::endian only supprts sizeof(double) == 8; please report error to boost mailing list"); - return detail::generic_reverse_endianness(x); + "boost::endian currently supports only sizeof(double) == 8;" + " please report static_assert failure to the boost mailing list"); + return detail::std_reverse_endianness(x); } template @@ -339,42 +349,29 @@ namespace endian {public: T operator()(T x) BOOST_NOEXCEPT {return reverse_endianness(x);}}; } - // compile-time generic convert return by value + // generic conditional reverse template - Reversible reverse_endianness(Reversible x) BOOST_NOEXCEPT - { + inline Reversible conditional_reverse(Reversible from) BOOST_NOEXCEPT { // work around lack of function template partial specialization by instantiating // a function object of a class that is partially specialized on the two order // template parameters, and then calling its operator(). detail::value_converter tmp; - return tmp(x); - } - - inline BOOST_SCOPED_ENUM(order) - effective_order(BOOST_SCOPED_ENUM(order) o) BOOST_NOEXCEPT - { - return o != order::native ? o : - # ifdef BOOST_LITTLE_ENDIAN - order::little -# else - order::big -# endif - ; + return tmp(from); } + // runtime conditional reverse template - Reversible reverse_endianness(Reversible from, + inline Reversible runtime_conditional_reverse(Reversible from, BOOST_SCOPED_ENUM(order) from_order, BOOST_SCOPED_ENUM(order) to_order) BOOST_NOEXCEPT { - return effective_order(from_order) == effective_order(to_order) - ? from : reverse_endianness(from); + return from_order == to_order ? from : reverse_endianness(from); } //--------------------------------------------------------------------------------------// -// reverse in place implementation // +// reverse-in-place implementation // //--------------------------------------------------------------------------------------// - // reverse byte-order in place (i.e. flip endianness) + // customization for built-in arithmetic types inline void reverse_endianness_in_place(int8_t& x) BOOST_NOEXCEPT { x = reverse_endianness(x); } inline void reverse_endianness_in_place(int16_t& x) BOOST_NOEXCEPT @@ -449,9 +446,9 @@ namespace endian {public: void operator()(T& x) BOOST_NOEXCEPT { reverse_endianness_in_place(x); }}; } // namespace detail - // fully generic conditional reverse in place + // generic conditional reverse in place template - void reverse_endianness_in_place(Reversible& x) BOOST_NOEXCEPT + inline void conditional_reverse_in_place(Reversible& x) BOOST_NOEXCEPT { // work around lack of function template partial specialization by instantiating // a function object of a class that is partially specialized on the two order @@ -462,10 +459,11 @@ namespace endian // runtime reverse in place template - void reverse_endianness_in_place(Reversible& x, BOOST_SCOPED_ENUM(order) from_order, - BOOST_SCOPED_ENUM(order) to_order) BOOST_NOEXCEPT + inline void runtime_conditional_reverse_in_place(Reversible& x, + BOOST_SCOPED_ENUM(order) from_order, BOOST_SCOPED_ENUM(order) to_order) + BOOST_NOEXCEPT { - if (effective_order(from_order) != effective_order(to_order)) + if (from_order != to_order) reverse_endianness_in_place(x); } diff --git a/test/conversion_test.cpp b/test/conversion_test.cpp index 82bb193..75b2222 100644 --- a/test/conversion_test.cpp +++ b/test/conversion_test.cpp @@ -134,85 +134,97 @@ namespace big_value(big); little_value(little); - // one-way tests + // validate the values used by the tests below + +# ifdef BOOST_BIG_ENDIAN + BOOST_TEST_EQ(native, big); + BOOST_TEST_EQ(be::detail::std_reverse_endianness(native), little); +# else + BOOST_TEST_EQ(be::detail::std_reverse_endianness(native), big); + BOOST_TEST_EQ(native, little); +# endif + + // unconditional reverse BOOST_TEST_EQ(be::reverse_endianness(big), little); BOOST_TEST_EQ(be::reverse_endianness(little), big); -// BOOST_TEST_EQ(be::reverse(big), little); -// BOOST_TEST_EQ(be::reverse(little), big); + // conditional reverse BOOST_TEST_EQ(be::native_to_big(native), big); -// BOOST_TEST_EQ(be::native_to_big(native), big); BOOST_TEST_EQ(be::native_to_little(native), little); - // BOOST_TEST_EQ(be::native_to_little(native), little); + BOOST_TEST_EQ(be::big_to_native(big), native); + BOOST_TEST_EQ(be::little_to_native(little), native); - // round-trip tests + // generic conditional reverse - BOOST_TEST_EQ(be::big_to_native(be::native_to_big(native)), native); - BOOST_TEST_EQ(be::native_to_big(be::big_to_native(big)), big); - BOOST_TEST_EQ(be::big_to_native(be::native_to_big(little)), little); - - BOOST_TEST_EQ(be::little_to_native(be::native_to_little(native)), native); - BOOST_TEST_EQ(be::little_to_native(be::native_to_little(big)), big); - BOOST_TEST_EQ(be::little_to_native(be::native_to_little(little)), little); - -# ifdef BOOST_BIG_ENDIAN - BOOST_TEST_EQ(be::reverse_endianness(native), little); -// BOOST_TEST_EQ(be::detail::reverse(native), little); - BOOST_TEST_EQ(be::big_to_native(big), big); -// BOOST_TEST_EQ(be::big_endian(big), big); - BOOST_TEST_EQ(be::little_to_native(little), little); -// BOOST_TEST_EQ(be::big_endian(little), little); -# else - BOOST_TEST_EQ(be::reverse_endianness(native), big); -// BOOST_TEST_EQ(be::detail::reverse(native), big); - BOOST_TEST_EQ(be::big_to_native(big), little); -// BOOST_TEST_EQ(be::big_endian(big), little); - BOOST_TEST_EQ(be::native_to_big(little), big); -// BOOST_TEST_EQ(be::big_endian(little), big); -# endif - - // compile time order determination test - - BOOST_TEST_EQ((be::reverse_endianness(big)), big); - BOOST_TEST_EQ((be::reverse_endianness(big)), big); + BOOST_TEST_EQ((be::conditional_reverse(little)), little); - BOOST_TEST_EQ((be::reverse_endianness(native)), native); - BOOST_TEST_EQ((be::reverse_endianness(big)), little); - BOOST_TEST_EQ((be::reverse_endianness(big)), native); - BOOST_TEST_EQ((be::reverse_endianness(little)), big); - BOOST_TEST_EQ((be::reverse_endianness(little)), native); - BOOST_TEST_EQ((be::reverse_endianness(native)), big); - BOOST_TEST_EQ((be::reverse_endianness(native)), little); - // runtime order determination test + // runtime conditional reverse - BOOST_TEST_EQ((be::reverse_endianness(big, be::order::big, be::order::big)), big); - BOOST_TEST_EQ((be::reverse_endianness(little, be::order::little, + BOOST_TEST_EQ((be::runtime_conditional_reverse(big, be::order::big, be::order::big)), + big); + BOOST_TEST_EQ((be::runtime_conditional_reverse(little, be::order::little, be::order::little)), little); - BOOST_TEST_EQ((be::reverse_endianness(native, be::order::native, + BOOST_TEST_EQ((be::runtime_conditional_reverse(native, be::order::native, be::order::native)), native); - BOOST_TEST_EQ((be::reverse_endianness(big, be::order::big, be::order::little)), - little); - BOOST_TEST_EQ((be::reverse_endianness(big, be::order::big, be::order::native)), - native); - BOOST_TEST_EQ((be::reverse_endianness(little, be::order::little, be::order::big)), - big); - BOOST_TEST_EQ((be::reverse_endianness(little, be::order::little, be::order::native)), - native); - BOOST_TEST_EQ((be::reverse_endianness(native, be::order::native, be::order::big)), - big); - BOOST_TEST_EQ((be::reverse_endianness(native, be::order::native, be::order::little)), - little); + BOOST_TEST_EQ((be::runtime_conditional_reverse(big, be::order::big, + be::order::little)), little); + BOOST_TEST_EQ((be::runtime_conditional_reverse(big, be::order::big, + be::order::native)), native); + BOOST_TEST_EQ((be::runtime_conditional_reverse(little, be::order::little, + be::order::big)), big); + BOOST_TEST_EQ((be::runtime_conditional_reverse(little, be::order::little, + be::order::native)), native); + BOOST_TEST_EQ((be::runtime_conditional_reverse(native, be::order::native, + be::order::big)), big); + BOOST_TEST_EQ((be::runtime_conditional_reverse(native, be::order::native, + be::order::little)), little); + + +// // round-trip tests +// +// BOOST_TEST_EQ(be::big_to_native(be::native_to_big(native)), native); +// BOOST_TEST_EQ(be::native_to_big(be::big_to_native(big)), big); +// BOOST_TEST_EQ(be::big_to_native(be::native_to_big(little)), little); +// +// BOOST_TEST_EQ(be::little_to_native(be::native_to_little(native)), native); +// BOOST_TEST_EQ(be::little_to_native(be::native_to_little(big)), big); +// BOOST_TEST_EQ(be::little_to_native(be::native_to_little(little)), little); +// +//# ifdef BOOST_BIG_ENDIAN +// BOOST_TEST_EQ(be::reverse_endianness(native), little); +// BOOST_TEST_EQ(be::detail::reverse(native), little); +// BOOST_TEST_EQ(be::big_to_native(big), big); +// BOOST_TEST_EQ(be::big_endian(big), big); +// BOOST_TEST_EQ(be::little_to_native(little), little); +// BOOST_TEST_EQ(be::big_endian(little), little); +//# else // little endian +// BOOST_TEST_EQ(be::reverse_endianness(native), big); +// BOOST_TEST_EQ(be::detail::std_reverse_endianness(native), big); +// BOOST_TEST_EQ(be::big_to_native(big), little); +//// BOOST_TEST_EQ(be::big_endian(big), little); +// BOOST_TEST_EQ(be::native_to_big(little), big); +//// BOOST_TEST_EQ(be::big_endian(little), big); +//# endif + // // light test of modify-in-place functions //