20namespace tcspc::internal {
37template <
typename BinIndex>
struct bin_increment_cluster_encoding_traits {
38 using encoded_size_type = std::make_unsigned_t<BinIndex>;
39 static_assert(
sizeof(encoded_size_type) <=
sizeof(std::size_t));
40 static constexpr auto encoded_size_max =
41 std::numeric_limits<encoded_size_type>::max();
42 static constexpr auto large_size_element_count =
43 sizeof(std::size_t) /
sizeof(encoded_size_type);
46template <
typename BinIndex>
47[[nodiscard]]
constexpr auto
48encoded_bin_increment_cluster_size(std::size_t cluster_size)
noexcept
50 using traits = bin_increment_cluster_encoding_traits<BinIndex>;
51 bool const is_long_mode = cluster_size >= traits::encoded_size_max;
52 std::size_t
const size_of_size =
53 is_long_mode ? 1 + traits::large_size_element_count : 1;
54 return size_of_size + cluster_size;
64template <
typename BinIndex,
typename Storage>
66encode_bin_increment_cluster(Storage dest, std::span<BinIndex const> cluster)
68 using traits = bin_increment_cluster_encoding_traits<BinIndex>;
70 std::size_t
const size = cluster.size();
71 bool const is_long_mode = size >= traits::encoded_size_max;
72 std::size_t
const size_of_size =
73 is_long_mode ? 1 + traits::large_size_element_count : 1;
74 std::size_t
const total_size = size_of_size + size;
75 if (total_size > dest.available_capacity())
78 auto spn = dest.make_space(total_size);
80 spn.front() =
static_cast<BinIndex
>(traits::encoded_size_max);
82 auto const size_dest = std::as_writable_bytes(
83 spn.subspan(0, traits::large_size_element_count));
84 assert(size_dest.size() ==
sizeof(size));
85 std::memcpy(size_dest.data(), &size,
sizeof(size));
86 spn = spn.subspan(size_dest.size());
88 spn.front() =
static_cast<BinIndex
>(
89 static_cast<traits::encoded_size_type
>(size));
92 assert(spn.size() == cluster.size());
93 std::copy(cluster.begin(), cluster.end(), spn.begin());
97template <
typename BinIndex>
class bin_increment_cluster_decoder {
98 using traits = bin_increment_cluster_encoding_traits<BinIndex>;
100 std::span<BinIndex const> clusters;
103 explicit bin_increment_cluster_decoder(std::span<BinIndex const> clusters)
104 : clusters(clusters) {}
109 class const_iterator {
110 std::span<BinIndex const>::iterator it;
114 auto cluster_range() const -> std::pair<decltype(it), decltype(it)> {
115 bool const is_long_mode =
static_cast<traits::encoded_size_type
>(
116 *it) == traits::encoded_size_max;
117 std::size_t
const size_of_size =
118 is_long_mode ? 1 + traits::large_size_element_count : 1;
119 std::size_t
const cluster_size =
120 is_long_mode ? std::invoke([sit = std::next(it)] {
122 std::memcpy(&size, &*sit,
sizeof(size));
125 : static_cast<traits::encoded_size_type>(*it);
127 std::next(it,
static_cast<std::ptrdiff_t
>(size_of_size));
129 std::next(start,
static_cast<std::ptrdiff_t
>(cluster_size));
130 return {start,
stop};
133 explicit const_iterator(
decltype(it) iter) : it(iter) {}
135 friend class bin_increment_cluster_decoder;
138 using value_type = std::span<BinIndex const>;
139 using difference_type = std::ptrdiff_t;
140 using reference = value_type
const &;
141 using pointer = value_type
const *;
142 using iterator_category = std::input_iterator_tag;
144 const_iterator() =
delete;
146 auto operator++() -> const_iterator & {
147 auto const [start,
stop] = cluster_range();
152 auto operator++(
int) -> const_iterator {
153 auto const ret = *
this;
158 auto operator*() const -> value_type {
159 auto const [start,
stop] = cluster_range();
160 return std::span(&*start, &*
stop);
163 auto operator==(const_iterator
const &)
const noexcept
167 [[nodiscard]]
auto begin() const noexcept -> const_iterator {
168 return const_iterator(clusters.begin());
171 [[nodiscard]]
auto end() const noexcept -> const_iterator {
172 return const_iterator(clusters.end());
177template <
typename BinIndex>
178bin_increment_cluster_decoder(std::span<BinIndex>)
179 -> bin_increment_cluster_decoder<BinIndex>;
auto stop(std::string message_prefix, Downstream downstream)
Create a processor that ends the stream when a given event type is received.
Definition stop.hpp:151