CCSDS 124.0-B-1 C++ 1.0.0
CCSDS 124.0-B-1 Lossless Compression
Loading...
Searching...
No Matches
decoder.hpp
Go to the documentation of this file.
1
27#ifndef CCSDS124_DECODER_HPP
28#define CCSDS124_DECODER_HPP
29
30#include "bitreader.hpp"
31#include "bitvector.hpp"
32#include "config.hpp"
33#include "error.hpp"
34
35namespace ccsds124 {
36
50inline Error count_decode(BitReader& reader, std::uint32_t& value) noexcept {
51 if (reader.remaining() == 0) {
52 return Error::Underflow;
53 }
54
55 // Read first bit
56 int bit0 = reader.read_bit();
57 if (bit0 < 0) {
58 return Error::Underflow;
59 }
60
61 if (bit0 == 0) {
62 // Case 1: '0' → value is 1
63 value = 1;
64 return Error::Ok;
65 }
66
67 // First bit is 1, read second bit
68 int bit1 = reader.read_bit();
69 if (bit1 < 0) {
70 return Error::Underflow;
71 }
72
73 if (bit1 == 0) {
74 // Case 2: '10' → terminator (value 0)
75 value = 0;
76 return Error::Ok;
77 }
78
79 // First two bits are 11, read third bit
80 int bit2 = reader.read_bit();
81 if (bit2 < 0) {
82 return Error::Underflow;
83 }
84
85 if (bit2 == 0) {
86 // Case 3: '110' + 5 bits → value + 2
87 std::uint32_t raw = reader.read_bits(5);
88 value = raw + 2;
89 return Error::Ok;
90 }
91
92 // Case 4: '111' + variable bits
93 // Count zeros to determine field size
94 std::size_t size = 0;
95 int next_bit;
96 do {
97 next_bit = reader.read_bit();
98 if (next_bit < 0) {
99 return Error::Underflow;
100 }
101 ++size;
102 } while (next_bit == 0 && reader.remaining() > 0);
103
104 // Size of value field is size + 5
105 std::size_t value_bits = size + 5;
106
107 // The '1' bit we just read is part of the value, so we need to account for it
108 // Read the remaining bits (value_bits - 1) and combine with the leading 1
109 std::uint32_t raw = 1; // Start with the leading 1
110 for (std::size_t i = 0; i < value_bits - 1; ++i) {
111 int bit = reader.read_bit();
112 if (bit < 0) {
113 return Error::Underflow;
114 }
115 raw = (raw << 1) | (static_cast<std::uint32_t>(bit) & 1U);
116 }
117
118 value = raw + 2;
119 return Error::Ok;
120}
121
132template <std::size_t N> Error rle_decode(BitReader& reader, BitVector<N>& result) noexcept {
133 // Initialize result to all zeros
134 result.zero();
135
136 // Start from end of vector (matching RLE encoding which processes LSB to MSB)
137 std::size_t bit_position = N;
138
139 // Read COUNT values until terminator
140 std::uint32_t delta = 0;
141 auto status = count_decode(reader, delta);
142
143 while (status == Error::Ok && delta != 0) {
144 // Delta represents (count of zeros + 1). A delta beyond the
145 // remaining bit position means the encoding is invalid for this
146 // vector length (GOTCHAS #20): reject it instead of silently
147 // skipping.
148 if (delta > bit_position) {
149 return Error::Overflow;
150 }
151 bit_position -= delta;
152 // Set the bit at this position
153 result.set_bit(bit_position, 1);
154
155 // Read next delta
156 status = count_decode(reader, delta);
157 }
158
159 return status;
160}
161
174template <std::size_t N>
175Error bit_insert(BitReader& reader, BitVector<N>& data, const BitVector<N>& mask) noexcept {
176 std::size_t hamming = mask.hamming_weight();
177
178 if (hamming == 0) {
179 // No bits to insert
180 return Error::Ok;
181 }
182
183 // GOTCHAS #20: fail on underflow instead of silently skipping positions
184 if (reader.remaining() < hamming) {
185 return Error::Underflow;
186 }
187
188 // Insert bits in reverse order (LSB to MSB, matching BE extraction)
189 // Iterate by set bits using __builtin_ctz for efficiency
190 for (int word = static_cast<int>(BitVector<N>::NUM_WORDS) - 1; word >= 0; --word) {
191 std::uint32_t mask_word = mask.data()[word];
192
193 // Loop bounded by popcount - guarantees termination
194 for (int bits_remaining = __builtin_popcount(mask_word); bits_remaining > 0;
195 --bits_remaining) {
196 // Find LSB position using extract_lsb helper
197 int bit_pos_in_word = detail::extract_lsb(mask_word);
198 std::size_t global_pos =
199 (static_cast<std::size_t>(word) * 32) + static_cast<std::size_t>(bit_pos_in_word);
200
201 if (global_pos < N) {
202 int bit = reader.read_bit();
203 if (bit < 0) {
204 return Error::Underflow;
205 }
206 data.set_bit(global_pos, bit);
207 }
208 }
209 }
210
211 return Error::Ok;
212}
213
226template <std::size_t N>
227Error bit_insert_forward(BitReader& reader, BitVector<N>& data, const BitVector<N>& mask) noexcept {
228 // GOTCHAS #20: fail on underflow instead of silently skipping positions
229 if (reader.remaining() < mask.hamming_weight()) {
230 return Error::Underflow;
231 }
232
233 // Insert bits in forward order (MSB to LSB)
234 // Iterate by set bits using __builtin_clz for efficiency
235 for (std::size_t word = 0; word < BitVector<N>::NUM_WORDS; ++word) {
236 std::uint32_t mask_word = mask.data()[word];
237
238 // Loop bounded by popcount - guarantees termination
239 for (int bits_remaining = __builtin_popcount(mask_word); bits_remaining > 0;
240 --bits_remaining) {
241 // Find MSB position using extract_msb helper
242 int clz = detail::extract_msb(mask_word);
243 std::size_t global_pos = (word * 32) + static_cast<std::size_t>(clz);
244
245 if (global_pos < N) {
246 int bit = reader.read_bit();
247 if (bit < 0) {
248 return Error::Underflow;
249 }
250 data.set_bit(global_pos, bit);
251 }
252 }
253 }
254
255 return Error::Ok;
256}
257
258} // namespace ccsds124
259
260#endif // CCSDS124_DECODER_HPP
Sequential bit reading from compressed data.
Fixed-length bit vector with static allocation.
Sequential bit reader for compressed data.
Definition bitreader.hpp:38
Fixed-length bit vector with compile-time size.
Definition bitvector.hpp:90
CCSDS 124.0-B-1 compile-time configuration.
CCSDS 124.0-B-1 error handling.
int extract_msb(std::uint32_t &word) noexcept
Extract and clear the most significant set bit from a word.
Definition bitvector.hpp:56
int extract_lsb(std::uint32_t &word) noexcept
Extract and clear the least significant set bit from a word.
Definition bitvector.hpp:71
Error bit_insert_forward(BitReader &reader, BitVector< N > &data, const BitVector< N > &mask) noexcept
Bit insertion with forward order.
Definition decoder.hpp:227
Error
Error codes for error-code-based error handling.
Definition error.hpp:29
@ Underflow
Buffer underflow (not enough data)
@ Overflow
Buffer overflow.
Error count_decode(BitReader &reader, std::uint32_t &value) noexcept
Counter decoding (inverse of CCSDS Section 5.2.2, Equation 9).
Definition decoder.hpp:50
Error rle_decode(BitReader &reader, BitVector< N > &result) noexcept
Run-length decoding (inverse of CCSDS Section 5.2.3, Equation 10).
Definition decoder.hpp:132
Error bit_insert(BitReader &reader, BitVector< N > &data, const BitVector< N > &mask) noexcept
Bit insertion (inverse of CCSDS Section 5.2.4, Equation 11).
Definition decoder.hpp:175