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<typename 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 typename std::span<BinIndex const>::iterator it;
114 auto cluster_range() const -> std::pair<decltype(it), decltype(it)> {
115 bool const is_long_mode =
116 static_cast<typename traits::encoded_size_type
>(*it) ==
117 traits::encoded_size_max;
118 std::size_t
const size_of_size =
119 is_long_mode ? 1 + traits::large_size_element_count : 1;
120 std::size_t
const cluster_size =
122 ? std::invoke([sit = std::next(it)] {
124 std::memcpy(&size, &*sit,
sizeof(size));
127 : static_cast<typename traits::encoded_size_type>(*it);
129 std::next(it,
static_cast<std::ptrdiff_t
>(size_of_size));
131 std::next(start,
static_cast<std::ptrdiff_t
>(cluster_size));
132 return {start,
stop};
135 explicit const_iterator(
decltype(it) iter) : it(iter) {}
137 friend class bin_increment_cluster_decoder;
140 using value_type = std::span<BinIndex const>;
141 using difference_type = std::ptrdiff_t;
142 using reference = value_type
const &;
143 using pointer = value_type
const *;
144 using iterator_category = std::input_iterator_tag;
146 const_iterator() =
delete;
148 auto operator++() -> const_iterator & {
149 auto const [start,
stop] = cluster_range();
154 auto operator++(
int) -> const_iterator {
155 auto const ret = *
this;
160 auto operator*() const -> value_type {
161 auto const [start,
stop] = cluster_range();
162 return std::span(&*start, &*
stop);
165 auto operator==(const_iterator
const &)
const noexcept
169 [[nodiscard]]
auto begin() const noexcept -> const_iterator {
170 return const_iterator(clusters.begin());
173 [[nodiscard]]
auto end() const noexcept -> const_iterator {
174 return const_iterator(clusters.end());
179template <
typename BinIndex>
180bin_increment_cluster_decoder(std::span<BinIndex>)
181 -> 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:138