diff --git a/doc/endian.adoc b/doc/endian.adoc index 1b7c06d..d038127 100644 --- a/doc/endian.adoc +++ b/doc/endian.adoc @@ -18,12 +18,14 @@ Beman Dawes include::endian/overview.adoc[] +include::endian/changelog.adoc[] + include::endian/conversion.adoc[] -include::endian/arithmetic.adoc[] - include::endian/buffers.adoc[] +include::endian/arithmetic.adoc[] + include::endian/choosing_approach.adoc[] include::endian/mini_review_topics.adoc[] @@ -36,5 +38,6 @@ include::endian/mini_review_topics.adoc[] This documentation is * Copyright 2011-2016 Beman Dawes +* Copyright 2019 Peter Dimov and is distributed under the http://www.boost.org/LICENSE_1_0.txt[Boost Software License, Version 1.0]. diff --git a/doc/endian/arithmetic.adoc b/doc/endian/arithmetic.adoc index 43c5e55..6d9743e 100644 --- a/doc/endian/arithmetic.adoc +++ b/doc/endian/arithmetic.adoc @@ -7,6 +7,7 @@ Distributed under the Boost Software License, Version 1.0. [#arithmetic] # Endian Arithmetic Types +:idprefix: arithmetic_ ## Introduction @@ -151,9 +152,9 @@ will no longer be relying on unspecified behavior. Two scoped enums are provided: ``` -enum class order {big, little, native}; +enum class order { big, little, native }; -enum class align {no, yes}; +enum class align { no, yes }; ``` One class template is provided: @@ -209,10 +210,9 @@ and to improve code readability and searchability. ## Class template `endian_arithmetic` -An `endian_integer` is an integer byte-holder with user-specified -<>, value type, size, and -<>. The usual operations on arithmetic types -are supplied. +An `endian_integer` is an integer byte-holder with user-specified endianness, +value type, size, and alignment. The usual operations on arithmetic types are +supplied. ### Synopsis @@ -225,7 +225,7 @@ namespace boost { // C++11 features emulated if not available - enum class align {no, yes}; + enum class align { no, yes }; template @@ -233,6 +233,7 @@ namespace boost : public endian_buffer { public: + typedef T value_type; // if BOOST_ENDIAN_FORCE_PODNESS is defined && C++11 PODs are not @@ -389,7 +390,7 @@ When `Nbits` is less than `sizeof(T)*8`, `T` must be a standard integral type ### Members ``` -endian_arithmetic() = default; // C++03: endian(){} +endian_arithmetic() noexcept = default; // C++03: endian(){} ``` [none] * {blank} @@ -397,38 +398,29 @@ endian_arithmetic() = default; // C++03: endian(){} Effects:: Constructs an uninitialized object. ``` -endian_arithmetic(T v); +endian_arithmetic(T v) noexcept; ``` [none] * {blank} + -Postcondition:: `*this == v`. +Effects:: See `endian_buffer::endian_buffer(T)`. ``` -endian_arithmetic& operator=(T v); +endian_arithmetic& operator=(T v) noexcept; ``` [none] * {blank} + -Postcondition:: `*this == v`. +Effects:: See `endian_buffer::operator=(T)`. Returns:: `*this`. ``` -operator T() const; +operator T() const noexcept; ``` [none] * {blank} + -Returns:: The current value stored in `*this`, converted to `value_type`. - -``` -const char* data() const; -``` -[none] -* {blank} -+ -Returns:: A pointer to the first byte of the endian binary value stored in -`*this`. +Returns:: `value()`. ### Other operators @@ -470,7 +462,7 @@ Returns:: `is`. ## FAQ -See the <> FAQ for a library-wide FAQ. +See the <> for a library-wide FAQ. Why not just use Boost.Serialization?:: Serialization involves a conversion for every object involved in I/O. Endian diff --git a/doc/endian/buffers.adoc b/doc/endian/buffers.adoc index 797d040..617d990 100644 --- a/doc/endian/buffers.adoc +++ b/doc/endian/buffers.adoc @@ -7,6 +7,7 @@ Distributed under the Boost Software License, Version 1.0. [#buffers] # Endian Buffer Types +:idprefix: buffers_ ## Introduction @@ -124,7 +125,7 @@ related to 8-bit bytes, and there have been no real-world use cases presented for other sizes. In {cpp}03, `endian_buffer` does not meet the requirements for POD types because -it has constructors, private data members, and a base class. This means that +it has constructors and a private data member. This means that common use cases are relying on unspecified behavior in that the {cpp} Standard does not guarantee memory layout for non-POD types. This has not been a problem in practice since all known {cpp} compilers lay out memory as if `endian` were @@ -146,9 +147,9 @@ relying on unspecified behavior. Two scoped enums are provided: ``` -enum class order {big, little, native}; +enum class order { big, little, native }; -enum class align {no, yes}; +enum class align { no, yes }; ``` One class template is provided: @@ -205,8 +206,7 @@ enable generic code, and to improve code readability and searchability. ## Class template `endian_buffer` An `endian_buffer` is a byte-holder for arithmetic types with -user-specified <>, value type, size, and -<>. +user-specified endianness, value type, size, and alignment. ### Synopsis @@ -217,13 +217,14 @@ namespace boost { // C++11 features emulated if not available - enum class align {no, yes}; + enum class align { no, yes }; template class endian_buffer { public: + typedef T value_type; endian_buffer() noexcept = default; @@ -234,7 +235,8 @@ namespace boost const char* data() const noexcept; private: - implementaton-defined endian_value; // for exposition only + + unsigned char value_[ Nbits / CHAR_BIT]; // exposition only }; // stream inserter @@ -347,13 +349,10 @@ namespace boost The `implementation-defined` text in typedefs above is either `big` or `little` according to the native endianness of the platform. -The expository data member `endian_value` stores the current value of an -`endian_value` object as a sequence of bytes ordered as specified by the -`Order` template parameter. The `implementation-defined` type of -`endian_value` is a type such as `char[Nbits/CHAR_BIT]` or `T` that meets the -requirements imposed by the `Nbits` and `Align` template parameters. The -`CHAR_BIT` macro is defined in ``. The only value of -`CHAR_BIT` that is required to be supported is 8. +The expository data member `value_` stores the current value of the +`endian_buffer` object as a sequence of bytes ordered as specified by the +`Order` template parameter. The `CHAR_BIT` macro is defined in ``. +The only supported value of `CHAR_BIT` is 8. The valid values of `Nbits` are as follows: @@ -386,8 +385,7 @@ explicit endian_buffer(T v) noexcept; [none] * {blank} + -Postcondition:: `value() == v & mask`, where `mask` is a constant of type -`value_type` with `Nbits` low-order bits set to one. +Effects:: `endian_store( &value_, v )`. ``` endian_buffer& operator=(T v) noexcept; @@ -395,8 +393,7 @@ endian_buffer& operator=(T v) noexcept; [none] * {blank} + -Postcondition:: `value() == v & mask`, where `mask` is a constant of type -`value_type` with `Nbits` low-order bits set to one. +Effects:: `endian_store( &value_, v )`. Returns:: `*this`. ``` @@ -405,8 +402,7 @@ value_type value() const noexcept; [none] * {blank} + -Returns:: `endian_value`, converted to `value_type`, if required, and having the -endianness of the native platform. +Returns:: `endian_load( &value_ )`. ``` const char* data() const noexcept; @@ -414,8 +410,7 @@ const char* data() const noexcept; [none] * {blank} + -Returns:: A pointer to the first byte of `endian_value`. -[none] +Returns:: A pointer to the first byte of `value_`. ### Non-member functions @@ -450,7 +445,7 @@ Returns:: `is`. ## FAQ -See the <> FAQ for a library-wide FAQ. +See the <> for a library-wide FAQ. Why not just use Boost.Serialization?:: Serialization involves a conversion for every object involved in I/O. Endian diff --git a/doc/endian/changelog.adoc b/doc/endian/changelog.adoc new file mode 100644 index 0000000..1b19064 --- /dev/null +++ b/doc/endian/changelog.adoc @@ -0,0 +1,19 @@ +//// +Copyright 2019 Peter Dimov + +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 +//// + +[#changelog] +# Revision History + +## Changes in 1.71.0 + +* Clarified requirements on the value type template parameter +* Added support for `float` and `double` +* Added `endian_load`, `endian_store` +* Updated `endian_reverse` to correctly support all non-`bool` integral types +* Moved deprecated names to the deprecated header `endian.hpp` diff --git a/doc/endian/choosing_approach.adoc b/doc/endian/choosing_approach.adoc index d9d0dc7..eb318ff 100644 --- a/doc/endian/choosing_approach.adoc +++ b/doc/endian/choosing_approach.adoc @@ -7,6 +7,7 @@ Distributed under the Boost Software License, Version 1.0. [#choosing] # Choosing Approach +:idprefix: choosing_ ## Introduction diff --git a/doc/endian/conversion.adoc b/doc/endian/conversion.adoc index 90a7d98..8b08d6a 100644 --- a/doc/endian/conversion.adoc +++ b/doc/endian/conversion.adoc @@ -7,6 +7,7 @@ Distributed under the Boost Software License, Version 1.0. [#conversion] # Endian Conversion Functions +:idprefix: conversion_ ## Introduction @@ -91,6 +92,12 @@ namespace endian void conditional_reverse_inplace(EndianReversibleInplace& x, order order1, order order2) noexcept; + template + T endian_load( unsigned char const * p ) noexcept; + + template + void endian_store( T const & v, unsigned char * p ) noexcept; + } // namespace endian } // namespace boost ``` @@ -244,7 +251,7 @@ EndianReversible conditional_reverse(EndianReversible x, [none] * {blank} + -Returns:: `order1 == order2 ? x : endian_reverse(x)`. +Returns:: `order1 == order2? x: endian_reverse(x)`. ``` template @@ -253,7 +260,7 @@ void endian_reverse_inplace(EndianReversible& x) noexcept; [none] * {blank} + -Effects:: `x` `= endian_reverse(x)`. +Effects:: `x = endian_reverse(x)`. ``` template @@ -310,11 +317,46 @@ void conditional_reverse_inplace(EndianReversibleInplace& x, * {blank} + Effects:: If `order1 == order2` then `endian_reverse_inplace(x)`. + +``` +template +T endian_load( unsigned char const * p ) noexcept; +``` [none] +* {blank} ++ +Requires:: `sizeof(T)` must be 1, 2, 4, or 8. `N` must be 1 when + `sizeof(T)` is 1, 2 when `sizeof(T)` is 2, 3 or 4 when `sizeof(T)` + is 4, and 5, 6, 7, or 8 when `sizeof(T)` is 8. `T` must be trivially + copyable. If `N` is not equal to `sizeof(T)`, `T` must be integral or + `enum`. + +Effects:: Reads `N` bytes starting from `p`, in forward or reverse order + depending on whether `Order` matches the native endianness or not, + interprets the resulting bit pattern as a value of type `T`, and returns it. + If `sizeof(T)` is bigger than `N`, zero-extends when `T` is unsigned, + sign-extends otherwise. + +``` +template +void endian_store( T const & v, unsigned char * p ) noexcept; +``` +[none] +* {blank} ++ +Requires:: `sizeof(T)` must be 1, 2, 4, or 8. `N` must be 1 when + `sizeof(T)` is 1, 2 when `sizeof(T)` is 2, 3 or 4 when `sizeof(T)` + is 4, and 5, 6, 7, or 8 when `sizeof(T)` is 8. `T` must be trivially + copyable. If `N` is not equal to `sizeof(T)`, `T` must be integral or + `enum`. + +Effects:: Writes to `p` the `N` least significant bytes from the object + representation of `v`, in forward or reverse order depending on whether + `Order` matches the native endianness or not. ## FAQ -See the <> FAQ for a library-wide FAQ. +See the <> for a library-wide FAQ. *Why are both value returning and modify-in-place functions provided?* diff --git a/doc/endian/overview.adoc b/doc/endian/overview.adoc index 4eadd5e..eb8c9e5 100644 --- a/doc/endian/overview.adoc +++ b/doc/endian/overview.adoc @@ -7,6 +7,7 @@ Distributed under the Boost Software License, Version 1.0. [#overview] # Overview +:idprefix: overview_ ## Abstract @@ -99,7 +100,7 @@ buffer types are provided for 16, 32, and 64-bit sizes. The provided specific types are typedefs for a generic class template that may be used directly for less common use cases. -<>:: +<>:: The application uses the provided endian arithmetic types, which supply the same operations as the built-in {cpp} arithmetic types. All conversions are implicit. Arithmetic sizes of 8, 16, 24, 32, 40, 48, 56, and 64 bits (i.e. 1, 2, 3, 4, 5, @@ -116,7 +117,7 @@ such as `noexcept`, are used only if available. See This section has been moved to its own <> page. -[#overview_intrinsic] +[#overview_intrinsics] ## Built-in support for Intrinsics Most compilers, including GCC, Clang, and Visual {cpp}, supply built-in support @@ -259,6 +260,7 @@ Iterations: 10'000'000'000, Intrinsics: `` `_byteswap_ushort`, etc. |64-bit aligned little endian |3.35 s |2.73 s |=== +[#overview_faq] ## Overall FAQ Is the implementation header only?:: @@ -268,7 +270,7 @@ Are {cpp}03 compilers supported?:: Yes. Does the implementation use compiler intrinsic built-in byte swapping?:: -Yes, if available. See <>. +Yes, if available. See <>. Why bother with endianness?:: Binary data portability is the primary use case. @@ -341,8 +343,7 @@ endianness for integers are one and the same problem. That is not true for floating point numbers, so binary serialization interfaces and formats for floating point does not fit well in an endian-based library. - -## Release history +## History ### Changes requested by formal review @@ -390,6 +391,7 @@ To support backward header compatibility, deprecated header transitioning to the official Boost release of the library as it will be removed in some future release. +[#overview_cpp03_support] ## {cpp}03 support for {cpp}11 features [%header,cols=2*]