解决方案要求:
// Returns false if nothing left.
int get_next_bits( uint8_t *len, uint32_t *bits );
// Sends the first `output_len` bytes pointed by `output`.
send_buffer( uint16_t output_len, const uint8_t *output );
// Allocated memory or array large enough for output.
// See below if this can't be guaranteed.
uint8_t *buf;
解决方案:
uint16_t output_len = 0;
uint8_t *output = buf; // Assumed to be large enough. But see below.
uint8_t available = 0; // Number of unassigned bits in `*output`.
uint32_t bits; // Bits to add to output.
uint8_t unassigned; // Number of bits (left) in `bits`.
while ( get_next_byte( &unassigned, &bits ) ) {
while ( unassigned > 0 ) {
if ( available == 0 ) {
// We need another byte of output.
// `output` already points to this byte.
++output_len;
*output = 0;
available = 8;
}
if ( available <= unassigned ) {
// We get here, for example, when we have
// 5 bits to insert but only 3 bits available in current output byte.
// So we shift the unassigned bits by 2 to place into position.
// And we're left 使用 0 available bits and 2 unassigned bits.
// We can't forget to "remove" from `bits` the 3 bits we assigned.
uint8_t shift = unassigned - available;
*output |= bits >> shift;
unassigned = shift;
bits &= 0xFF >> ( 8 - unassigned );
available = 0;
++output;
} else {
// We get here, for example, when we have
// 3 bits to insert and 5 bits available in current output byte.
// So we shift the unassigned bits by 2 to place into position.
// And we're left 使用 2 available bits and 0 unassigned bits.
uint8_t shift = available - unassigned;
*output |= bits << shift;
unassigned = 0;
available = shift;
}
}
}
send_buffer( output_len, output );
如果需要,available == unassigned
箱可以特别处理.
if ( available == unassigned ) {
// We get here, for example, when we have
// 5 bits to insert and 5 bits available in current output byte.
// We're left 使用 0 available bits and 0 unassigned bits.
*output |= bits;
unassigned = 0;
available = 0;
++output;
}
如果不能保证缓冲区足够大以容纳所有位,请替换
if ( available == 0 ) {
// We need another byte of output.
// `output` already points to this byte.
*output = 0;
available = 8;
++output_len;
}
使用
if ( available == 0 ) {
// We need another byte of output.
// `output` already points to this byte.
if ( output_len == buf_size ) {
// Buffer is full, so send and empty it.
output -= buf_size;
output_len = 0;
send_buffer( buf_size, output );
}
*output = 0;
available = 8;
++output_len;
}