POD => trivial, also clarify tstrlen

master
Daniel Kolesa 2018-01-13 22:33:46 +01:00
parent dab034d9e0
commit 69d5d11da1
2 changed files with 23 additions and 9 deletions

View File

@ -84,7 +84,7 @@ enum class stream_seek {
};
template<typename T = char, bool = std::is_pod_v<T>>
template<typename T = char, bool = std::is_trivial_v<T>>
struct stream_range;
/** @brief Thrown on stream errors. */
@ -398,7 +398,7 @@ struct stream {
* By default, it's a `char` range that can be read from if the stream
* can be read from and written into if the stream can be written into.
* You can override the type by passing in the template parameter. The
* type must always be POD.
* type must always be trivial.
*
* @tparam T The type to use for reading/writing (`char` by default).
*
@ -422,7 +422,7 @@ struct stream {
/** @brief Writes several values into the stream.
*
* Uses write_bytes() to write `count` values from `v` into the stream.
* The type must be POD.
* The type must be trivial.
*
* @throws ostd::stream_error on write failure.
*/
@ -433,7 +433,7 @@ struct stream {
/** @brief Writes a single value into the stream.
*
* Uses write_bytes() to write the value. The type must be POD.
* Uses write_bytes() to write the value. The type must be trivial.
*
* @throws ostd::stream_error on write failure.
*/
@ -447,7 +447,7 @@ struct stream {
* Uses read_bytes() to read `count` values into `v` from the stream.
* If an end-of-stream is encountered while reading, this does not
* throw, but it returns the number of entire values successfully read.
* The type must be POD.
* The type must be trivial.
*
* @returns The number of whole values read.
*
@ -462,7 +462,7 @@ struct stream {
/** @brief Reads a single value from the stream.
*
* If the value couldn't be read (reading failed or end-of-stream
* occured), this throws ostd::stream_error. The type must be POD.
* occured), this throws ostd::stream_error. The type must be trivial.
*
* @throws ostd::stream_error on read failure or end-of-stream.
*/
@ -476,7 +476,7 @@ struct stream {
/** @brief Reads a single value from the stream.
*
* If the value couldn't be read (reading failed or end-of-stream
* occured), this throws ostd::stream_error. The type must be POD.
* occured), this throws ostd::stream_error. The type must be trivial.
*
* @returns The read value.
*
@ -548,7 +548,7 @@ private:
* example).
*
* This template is a specialization of undefined base type because stream
* ranges only work with POD types.
* ranges only work with trivial types.
*
* @see stream_line_range
*/
@ -660,7 +660,7 @@ inline stream_range<T> stream::iter() {
* The lines are read using ostd::stream::get_line().
*
* You can provide a custom type for characters, by default it's `char`.
* It must be POD.
* It must be trivial.
*
* You can also provide a custom type used to hold the line, which must be a
* container type over `T` which can append at the end. By default,

View File

@ -20,24 +20,38 @@ template<typename C>
inline std::size_t tstrlen_impl(C const *p) noexcept {
using SL = std::numeric_limits<std::size_t>;
using UL = std::numeric_limits<std::make_unsigned_t<C>>;
/* low bits of each UL contained in SL (0000000100000001... etc) */
constexpr std::size_t Lbits = SL::max() / UL::max();
/* high bits of each UL contained in SL (1000000010000000... etc) */
constexpr std::size_t Hbits = Lbits << (UL::digits - 1);
C const *bp = p;
/* 1 unit or less per size_t, simple loop */
if constexpr(sizeof(C) >= sizeof(std::size_t)) {
goto sloop;
}
/* need a pointer aligned to sizeof(size_t) */
for (; std::uintptr_t(p) % sizeof(std::size_t); ++p) {
if (!*p) {
return (p - bp);
}
}
{
/* (e.g. x86_64 => sizeof(size_t) == 8 * sizeof(char) */
auto *wp = reinterpret_cast<std::size_t const *>(p);
/* check if any unit in the size_t is zero, in binary:
*
* XXX1 - 0001 => XXX0; XXX0 & YYY0 => 0000; 0000 & 1000 => 0000
* XX10 - 0001 => XX01; XX01 & YY01 => 0001; 0001 & 1000 => 0000
* 0000 - 0001 => 1111; 1111 & 1111 => 1111; 1111 & 1000 => 1000
*
* if the check passes, a terminating zero is in that size_t, break
*/
for (; !(((*wp - Lbits) & ~*wp) & Hbits); ++wp) {}
p = reinterpret_cast<C const *>(wp);
}
sloop:
/* either all of the string if goto'd, or contains terminating zero */
for (; *p; ++p) {}
return (p - bp);
}