diff --git a/doc/endian/arithmetic.adoc b/doc/endian/arithmetic.adoc index 46e775f..10dd2e5 100644 --- a/doc/endian/arithmetic.adoc +++ b/doc/endian/arithmetic.adoc @@ -39,6 +39,7 @@ Implicit conversion to the underlying value type is provided. An implicit constructor converting from the underlying value type is provided. ## Example + The `endian_example.cpp` program writes a binary file containing four-byte, big-endian and little-endian integers: @@ -145,7 +146,7 @@ will no longer be relying on unspecified behavior. * Signed | unsigned * Unaligned | aligned * 1-8 byte (unaligned) | 1, 2, 4, 8 byte (aligned) -* Choice of value type +* Choice of value type ## Enums and typedefs @@ -210,7 +211,7 @@ and to improve code readability and searchability. ## Class template `endian_arithmetic` -An `endian_integer` is an integer byte-holder with user-specified endianness, +`endian_arithmetic` is an integer byte-holder with user-specified endianness, value type, size, and alignment. The usual operations on arithmetic types are supplied. @@ -568,6 +569,7 @@ Functions] feature is detected automatically, and will be used if present to ensure that objects of `class endian_arithmetic` are trivial, and thus PODs. ## Compilation + Boost.Endian is implemented entirely within headers, with no need to link to any Boost object libraries. diff --git a/doc/endian/changelog.adoc b/doc/endian/changelog.adoc index bac1e01..9ed85f5 100644 --- a/doc/endian/changelog.adoc +++ b/doc/endian/changelog.adoc @@ -10,6 +10,11 @@ http://www.boost.org/LICENSE_1_0.txt [#changelog] # Revision History +## Changes in 1.74.0 + +* Enabled scoped enumeration types in `endian_reverse` +* Enabled `bool`, `enum`, `float`, `double` in `endian_reverse_inplace` + ## Changes in 1.72.0 * Made `endian_reverse`, `conditional_reverse` and `\*\_to_*` `constexpr` diff --git a/doc/endian/conversion.adoc b/doc/endian/conversion.adoc index 0c3d117..a5e7892 100644 --- a/doc/endian/conversion.adoc +++ b/doc/endian/conversion.adoc @@ -35,8 +35,20 @@ _http://en.wikipedia.org/wiki/Gulliver's_Travels[Gulliver's Travels]_, where rival kingdoms opened their soft-boiled eggs at different ends. Wikipedia has an extensive description of https://en.wikipedia.org/wiki/Endianness[Endianness]. -The standard integral types ({cpp}std 3.9.1) except `bool` are collectively -called the *endian types*. +The standard integral types ({cpp}std [basic.fundamental]) except `bool` and +the scoped enumeration types ({cpp}std [dcl.enum]) are collectively called the +*endian types*. In the absence of padding bits, which is true on the platforms +supported by the Boost.Endian library, endian types have the property that all +of their bit patterns are valid values, which means that when an object of an +endian type has its constituent bytes reversed, the result is another valid value. +This allows `endian_reverse` to take and return by value. + +Other built-in types, such as `bool`, `float`, or unscoped enumerations, do not +have the same property, which means that reversing their constituent bytes may +produce an invalid value, leading to undefined behavior. These types are therefore +disallowed in `endian_reverse`, but are still allowed in `endian_reverse_inplace`. +Even if an object becomes invalid as a result of reversing its bytes, as long as +its value is never read, there would be no undefined behavior. ### Header `` Synopsis @@ -216,37 +228,37 @@ reversed. If `T` is a class type, the function: -* Returns the value of `x` with the order of bytes reversed for all data members -of types or arrays of types that meet the `EndianReversible` requirements, and; -* Is a non-member function in the same namespace as `T` that can be found by -argument dependent lookup (ADL). +* Is expected to be implemented by the user, as a non-member function in the same + namespace as `T` that can be found by argument dependent lookup (ADL); +* Should returns the value of `x` with the order of bytes reversed for all data members + of types or arrays of types that meet the `EndianReversible` requirements. |=== [#conversion_endianreversibleinplace] -##### EndianReversibleInplace requirements (in addition to `CopyConstructible`) +##### EndianReversibleInplace requirements [%header,cols=2*] |=== |Expression |Requirements |`endian_reverse_inplace(mlx)` -a|`T` is an endian type or a class type. +a|`T` is an integral type, an enumeration type, `float`, `double`, or a class type. -If `T` is an endian type, reverses the order of bytes in `mlx`. +If `T` is not a class type, reverses the order of bytes in `mlx`. If `T` is a class type, the function: -* Reverses the order of bytes of all data members of `mlx` that have types or -arrays of types that meet the `EndianReversible` or `EndianReversibleInplace` -requirements, and; -* Is a non-member function in the same namespace as `T` that can be found by -argument dependent lookup (ADL). +* Is expected to be implemented by the user, as a non-member function in the same + namespace as `T` that can be found by argument dependent lookup (ADL); +* Should reverse the order of bytes of all data members of `mlx` that have types or + arrays of types that meet the `EndianReversible` or `EndianReversibleInplace` + requirements. |=== NOTE: Because there is a function template for `endian_reverse_inplace` that -calls `endian_reverse`, only `endian_reverse` is required for a user-defined -type to meet the `EndianReversibleInplace` requirements. Although User-defined -types are not required to supply an `endian_reverse_inplace` function, doing so -may improve efficiency. +calls `endian_reverse` for class types, only `endian_reverse` is required for a +user-defined type to meet the `EndianReversibleInplace` requirements. Although +user-defined types are not required to supply an `endian_reverse_inplace` function, +doing so may improve efficiency. #### Customization points for user-defined types (UDTs) @@ -273,7 +285,8 @@ Endian endian_reverse(Endian x) noexcept; [none] * {blank} + -Requires:: `Endian` must be a standard integral type that is not `bool`. +Requires:: `Endian` must be a standard integral type that is not `bool`, + or a scoped enumeration type. Returns:: `x`, with the order of its constituent bytes reversed. ``` @@ -343,7 +356,11 @@ void endian_reverse_inplace(EndianReversible& x) noexcept; [none] * {blank} + -Effects:: `x = endian_reverse(x)`. +Effects:: When `EndianReversible` is a class type, + `x = endian_reverse(x);`. When `EndianReversible` is an integral + type, an enumeration type, `float`, or `double`, reverses the + order of the constituent bytes of `x`. Otherwise, the program is + ill-formed. ``` template @@ -526,17 +543,15 @@ Effects:: See the <> for a library-wide FAQ. -*Why are both value returning and modify-in-place functions provided?* - -* Returning the result by value is the standard C and {cpp} idiom for functions +Why are both value returning and modify-in-place functions provided?:: +Returning the result by value is the standard C and {cpp} idiom for functions that compute a value from an argument. Modify-in-place functions allow cleaner code in many real-world endian use cases and are more efficient for user-defined types that have members such as string data that do not need to be reversed. Thus both forms are provided. -*Why not use the Linux names (htobe16, htole16, be16toh, le16toh, etc.) ?* - -* Those names are non-standard and vary even between POSIX-like operating +Why not use the Linux names (htobe16, htole16, be16toh, le16toh, etc.) ?:: +Those names are non-standard and vary even between POSIX-like operating systems. A {cpp} library TS was going to use those names, but found they were sometimes implemented as macros. Since macros do not respect scoping and namespace rules, to use them would be very error prone. diff --git a/doc/endian/overview.adoc b/doc/endian/overview.adoc index 6086db3..951c81f 100644 --- a/doc/endian/overview.adoc +++ b/doc/endian/overview.adoc @@ -359,7 +359,8 @@ limitations, support for floating point types was not reliable and was removed. For example, simply reversing the endianness of a floating point number can result in a signaling-NAN. + -Support for `float` and `double` has since been reinstated for `endian_buffer` -and `endian_arithmetic`. The conversion functions still do not support floating +Support for `float` and `double` has since been reinstated for `endian_buffer`, +`endian_arithmetic` and the conversion functions that reverse endianness in place. +The conversion functions that take and return by value still do not support floating point due to the above issues; reversing the bytes of a floating point number does not necessarily produce another valid floating point number.