CCSDS 124.0-B-1 C 1.0.0
CCSDS 124.0-B-1 Lossless Compression
Loading...
Searching...
No Matches
bitbuffer.c
Go to the documentation of this file.
1
31#include "ccsds124.h"
32#include <string.h>
33
41 if (bb != NULL) {
42 bb->num_bits = 0U;
43 bb->acc = 0U;
44 bb->acc_len = 0U;
45 (void)memset(bb->data, 0, CCSDS124_MAX_OUTPUT_BYTES);
46 }
47}
48
49
53
/* End of Initialization Functions */
55
67 while (bb->acc_len >= 8U) {
68 /* Extract top 8 bits */
69 bb->acc_len -= 8U;
70 size_t byte_index = (bb->num_bits - bb->acc_len - 8U) / 8U;
71 bb->data[byte_index] = (uint8_t)(bb->acc >> bb->acc_len);
72 bb->acc &= ((1U << bb->acc_len) - 1U); /* Clear extracted bits */
73 }
74}
75
76
78 int result = CCSDS124_ERROR_INVALID_ARG;
79
80 if (bb != NULL) {
81 /* Check for overflow - CCSDS124_MAX_OUTPUT_BYTES * 8 bits */
82 size_t max_bits = CCSDS124_MAX_OUTPUT_BYTES * 8U;
83 if (bb->num_bits >= max_bits) {
85 } else {
86 /* Accumulate bit in MSB-first order */
87 uint32_t bit_val = ((uint32_t)bit) & 1U;
88 bb->acc = (bb->acc << 1U) | bit_val;
89 bb->acc_len++;
90 bb->num_bits++;
91
92 /* Flush when accumulator has 8+ bits */
93 if (bb->acc_len >= 8U) {
95 }
96
97 result = CCSDS124_OK;
98 }
99 }
100
101 return result;
102}
103
104
105int bitbuffer_append_bits(bitbuffer_t *bb, const uint8_t *data, size_t num_bits) {
106 int result = CCSDS124_ERROR_INVALID_ARG;
107
108 if ((bb != NULL) && (data != NULL)) {
109 /* Check for overflow - CCSDS124_MAX_OUTPUT_BYTES * 8 bits */
110 size_t max_bits = CCSDS124_MAX_OUTPUT_BYTES * 8U;
111 if ((bb->num_bits + num_bits) > max_bits) {
113 } else {
114 result = CCSDS124_OK;
115
116 /* Append each bit MSB-first */
117 for (size_t i = 0U; (i < num_bits) && (result == CCSDS124_OK); i++) {
118 size_t byte_index = i / 8U;
119 size_t bit_index = i % 8U;
120
121 /* Extract bits MSB-first (bit 7, 6, 5, ..., 0) */
122 uint32_t shift_amount = 7U - (uint32_t)bit_index;
123 uint32_t shifted = (uint32_t)data[byte_index] >> shift_amount;
124 uint32_t masked = shifted & 1U;
125 int bit = (int)masked;
126
127 result = bitbuffer_append_bit(bb, bit);
128 }
129 }
130 }
131
132 return result;
133}
134
135
151int bitbuffer_append_value(bitbuffer_t *bb, uint32_t value, size_t num_bits) {
152 int result = CCSDS124_ERROR_INVALID_ARG;
153
154 if ((bb != NULL) && (num_bits > 0U) && (num_bits <= 24U)) {
155 /* Check for overflow */
156 size_t max_bits = CCSDS124_MAX_OUTPUT_BYTES * 8U;
157 if ((bb->num_bits + num_bits) > max_bits) {
159 } else {
160 /* Add bits directly to accumulator.
161 * Value is right-justified: the bottom 'num_bits' bits are the data.
162 * Mask to ensure only the relevant bits are used. */
163 uint32_t mask = (1U << (uint32_t)num_bits) - 1U;
164 uint32_t masked_value = value & mask;
165
166 bb->acc = (bb->acc << (uint32_t)num_bits) | masked_value;
167 bb->acc_len += num_bits;
168 bb->num_bits += num_bits;
169
170 /* Flush complete bytes */
172
173 result = CCSDS124_OK;
174 }
175 }
176
177 return result;
178}
179
180
182 int result = CCSDS124_ERROR_INVALID_ARG;
183
184 if ((bb != NULL) && (bv != NULL)) {
185 result = CCSDS124_OK;
186
187 /* Calculate number of bytes from bit length */
188 size_t num_bytes = (bv->length + 7U) / 8U;
189
190 /* CCSDS MSB-first: bytes in order, but bits within each byte from MSB to LSB */
191 for (size_t byte_idx = 0U; (byte_idx < num_bytes) && (result == CCSDS124_OK); byte_idx++) {
192 size_t bits_in_this_byte = 8U;
193
194 /* Last byte may have fewer than 8 bits */
195 if (byte_idx == (num_bytes - 1U)) {
196 size_t remainder = bv->length % 8U;
197 if (remainder != 0U) {
198 bits_in_this_byte = remainder;
199 }
200 }
201
202 /* With MSB-first bitvector indexing: bit 0 is MSB, bit 7 is LSB
203 * We want to append bits in order: MSB first, LSB last
204 * So we iterate through positions 0, 1, 2, ..., bits_in_this_byte-1 */
205 size_t start_bit = byte_idx * 8U;
206 for (size_t bit_offset = 0U; (bit_offset < bits_in_this_byte) && (result == CCSDS124_OK); bit_offset++) {
207 size_t pos = start_bit + bit_offset;
208 int bit = bitvector_get_bit(bv, pos);
209
210 result = bitbuffer_append_bit(bb, bit);
211 }
212 }
213 }
214
215 return result;
216}
217
/* End of Bit Appending Functions */
219
226size_t bitbuffer_size(const bitbuffer_t *bb) {
227 size_t size = 0U;
228
229 if (bb != NULL) {
230 size = bb->num_bits;
231 }
232
233 return size;
234}
235
/* End of Query Functions */
237
244size_t bitbuffer_to_bytes(const bitbuffer_t *bb, uint8_t *data, size_t max_bytes) {
245 size_t num_bytes = 0U;
246
247 if ((bb != NULL) && (data != NULL)) {
248 /* Calculate number of bytes needed (ceiling division) */
249 num_bytes = (bb->num_bits + 7U) / 8U;
250
251 if (num_bytes > max_bytes) {
252 num_bytes = max_bytes;
253 }
254
255 /* Copy flushed bytes from data buffer */
256 size_t flushed_bytes = (bb->num_bits - bb->acc_len) / 8U;
257 if (flushed_bytes > num_bytes) {
258 flushed_bytes = num_bytes;
259 }
260 if (flushed_bytes > 0U) {
261 (void)memcpy(data, bb->data, flushed_bytes);
262 }
263
264 /* Handle remaining bits in accumulator */
265 if ((bb->acc_len > 0U) && (flushed_bytes < num_bytes)) {
266 /* Shift accumulator bits to MSB position */
267 uint8_t last_byte = (uint8_t)(bb->acc << (8U - bb->acc_len));
268 data[flushed_bytes] = last_byte;
269 }
270 }
271
272 return num_bytes;
273}
274
/* End of Byte Conversion Functions */
static void bitbuffer_flush_acc(bitbuffer_t *bb)
Flush accumulator to data buffer when it has 8+ bits.
Definition bitbuffer.c:66
CCSDS 124.0-B-1 Compression Library - Public API.
int bitbuffer_append_bitvector(bitbuffer_t *bb, const bitvector_t *bv)
Append all bits from a bit vector.
Definition bitbuffer.c:181
int bitbuffer_append_bits(bitbuffer_t *bb, const uint8_t *data, size_t num_bits)
Append multiple bits from byte array.
Definition bitbuffer.c:105
int bitbuffer_append_value(bitbuffer_t *bb, uint32_t value, size_t num_bits)
Append multiple bits from a value in a single operation.
Definition bitbuffer.c:151
int bitbuffer_append_bit(bitbuffer_t *bb, int bit)
Append a single bit to buffer.
Definition bitbuffer.c:77
void bitbuffer_clear(bitbuffer_t *bb)
Clear bit buffer contents.
Definition bitbuffer.c:50
void bitbuffer_init(bitbuffer_t *bb)
Initialize bit buffer to empty state.
Definition bitbuffer.c:40
size_t bitbuffer_size(const bitbuffer_t *bb)
Get number of bits in buffer.
Definition bitbuffer.c:226
size_t bitbuffer_to_bytes(const bitbuffer_t *bb, uint8_t *data, size_t max_bytes)
Convert bit buffer to byte array.
Definition bitbuffer.c:244
static int bitvector_get_bit(const bitvector_t *bv, size_t pos)
Get bit value at position (inline for performance).
Definition ccsds124.h:169
#define CCSDS124_MAX_OUTPUT_BYTES
Definition ccsds124.h:74
#define CCSDS124_ERROR_OVERFLOW
Definition ccsds124.h:49
#define CCSDS124_ERROR_INVALID_ARG
Definition ccsds124.h:48
#define CCSDS124_OK
Definition ccsds124.h:47
Variable-length bit buffer structure.
Definition ccsds124.h:308
uint8_t data[CCSDS124_MAX_OUTPUT_BYTES]
Definition ccsds124.h:309
size_t acc_len
Definition ccsds124.h:312
size_t num_bits
Definition ccsds124.h:310
uint32_t acc
Definition ccsds124.h:311
Fixed-length bit vector structure.
Definition ccsds124.h:133
size_t length
Definition ccsds124.h:135