Bitwise IO: Difference between revisions

Add source for Rust
No edit summary
(Add source for Rust)
Line 90:
1,0,0,0,0,1,1, -- C
1,0,1,0,1,0,1, -- U
1,0,1,0,0,1,1 -- S
);
Data : Bit_Array (ABACUS'Range);
Line 269:
<lang autohotkey>file = %A_WorkingDir%\z.dat
IfExist, %A_WorkingDir%\z.dat
FileDelete %file%
IfNotEqual ErrorLevel,0, MsgBox Can't delete file "%file%"`nErrorLevel = "%ErrorLevel%"
 
Line 453:
typedef uint8_t byte;
typedef struct {
FILE *fp;
uint32_t accu;
int bits;
} bit_io_t, *bit_filter;
 
bit_filter b_attach(FILE *f)
{
bit_filter b = malloc(sizeof(bit_io_t));
b->bits = b->accu = 0;
b->fp = f;
return b;
}
 
void b_write(byte *buf, size_t n_bits, size_t shift, bit_filter bf)
{
uint32_t accu = bf->accu;
int bits = bf->bits;
 
buf += shift / 8;
shift %= 8;
 
while (n_bits || bits >= 8) {
while (bits >= 8) {
bits -= 8;
fputc(accu >> bits, bf->fp);
accu &= (1 << bits) - 1;
}
}
while (bits < 8 && n_bits) {
accu = (accu << 1) | (((128 >> shift) & *buf) >> (7 - shift));
--n_bits;
bits++;
if (++shift == 8) {
shift = 0;
buf++;
}
}
}
}
}
}
bf->accu = accu;
bf->bits = bits;
}
 
size_t b_read(byte *buf, size_t n_bits, size_t shift, bit_filter bf)
{
uint32_t accu = bf->accu;
int bits = bf->bits;
int mask, i = 0;
 
buf += shift / 8;
shift %= 8;
 
while (n_bits) {
while (bits && n_bits) {
mask = 128 >> shift;
if (accu & (1 << (bits - 1))) *buf |= mask;
else *buf &= ~mask;
 
n_bits--;
bits--;
 
if (++shift >= 8) {
shift = 0;
buf++;
}
}
}
}
if (!n_bits) break;
accu = (accu << 8) | fgetc(bf->fp);
bits += 8;
}
}
bf->accu = accu;
bf->bits = bits;
 
return i;
}
 
void b_detach(bit_filter bf)
{
if (bf->bits) {
bf->accu <<= 8 - bf->bits;
fputc(bf->accu, bf->fp);
}
}
free(bf);
}
 
int main()
{
unsigned char s[] = "abcdefghijk";
unsigned char s2[11] = {0};
int i;
 
FILE *f = fopen("test.bin", "wb");
bit_filter b = b_attach(f);
/* for each byte in s, write 7 bits skipping 1 */
for (i = 0; i < 10; i++) b_write(s + i, 7, 1, b);
b_detach(b);
fclose(f);
 
/* read 7 bits and expand to each byte of s2 skipping 1 bit */
f = fopen("test.bin", "rb");
b = b_attach(f);
for (i = 0; i < 10; i++) b_read(s2 + i, 7, 1, b);
b_detach(b);
fclose(f);
 
printf("%10s\n", s2); /* should be the same first 10 bytes as in s */
 
return 0;
}</lang>
 
Line 1,303:
 
import (
"bufio"
"errors"
"io"
)
 
Line 1,312:
 
const (
// LSB is for Least Significant Bits first
LSB Order = iota
// MSB is for Most Significant Bits first
MSB
)
 
Line 1,321:
 
type writer interface {
io.ByteWriter
Flush() error
}
 
// Writer implements bit-wise writing to an io.Writer.
type Writer struct {
w writer
order Order
write func(uint32, uint) error // writeLSB or writeMSB
bits uint32
nBits uint
err error
}
 
// writeLSB writes `width` bits of `c` in LSB order.
func (w *Writer) writeLSB(c uint32, width uint) error {
w.bits |= c << w.nBits
w.nBits += width
for w.nBits >= 8 {
if err := w.w.WriteByte(uint8(w.bits)); err != nil {
return err
}
}
w.bits >>= 8
w.nBits -= 8
}
}
return nil
}
 
// writeMSB writes `width` bits of `c` in MSB order.
func (w *Writer) writeMSB(c uint32, width uint) error {
w.bits |= c << (32 - width - w.nBits)
w.nBits += width
for w.nBits >= 8 {
if err := w.w.WriteByte(uint8(w.bits >> 24)); err != nil {
return err
}
}
w.bits <<= 8
w.nBits -= 8
}
}
return nil
}
 
// WriteBits writes up to 16 bits of `c` to the underlying writer.
// Even for MSB ordering the bits are taken from the lower bits of `c`.
// (e.g.  WriteBits(0x0f,4) writes four 1 bits).
func (w *Writer) WriteBits(c uint16, width uint) error {
if w.err == nil {
w.err = w.write(uint32(c), width)
}
}
return w.err
}
 
Line 1,378:
// It does not close the underlying writer.
func (w *Writer) Close() error {
if w.err != nil {
if w.err == errClosed {
return nil
}
}
return w.err
}
}
// Write the final bits (zero padded).
if w.nBits > 0 {
if w.order == MSB {
w.bits >>= 24
}
}
if w.err = w.w.WriteByte(uint8(w.bits)); w.err != nil {
return w.err
}
}
}
}
w.err = w.w.Flush()
if w.err != nil {
return w.err
}
}
 
// Make any future calls to Write return errClosed.
w.err = errClosed
return nil
}
 
// NewWriter returns a new bit Writer that writes completed bytes to `w`.
func NewWriter(w io.Writer, order Order) *Writer {
bw := &Writer{order: order}
switch order {
case LSB:
bw.write = bw.writeLSB
case MSB:
bw.write = bw.writeMSB
default:
bw.err = errors.New("bit writer: unknown order")
return bw
}
}
if byteWriter, ok := w.(writer); ok {
bw.w = byteWriter
} else {
bw.w = bufio.NewWriter(w)
}
}
return bw
}
 
Line 1,427:
// Reader implements bit-wise reading from an io.Reader.
type Reader struct {
r io.ByteReader
bits uint32
nBits uint
read func(width uint) (uint16, error) // readLSB or readMSB
err error
}
 
func (r *Reader) readLSB(width uint) (uint16, error) {
for r.nBits < width {
x, err := r.r.ReadByte()
if err != nil {
return 0, err
}
}
r.bits |= uint32(x) << r.nBits
r.nBits += 8
}
}
bits := uint16(r.bits & (1<<width - 1))
r.bits >>= width
r.nBits -= width
return bits, nil
}
 
func (r *Reader) readMSB(width uint) (uint16, error) {
for r.nBits < width {
x, err := r.r.ReadByte()
if err != nil {
return 0, err
}
}
r.bits |= uint32(x) << (24 - r.nBits)
r.nBits += 8
}
}
bits := uint16(r.bits >> (32 - width))
r.bits <<= width
r.nBits -= width
return bits, nil
}
 
// ReadBits reads up to 16 bits from the underlying reader.
func (r *Reader) ReadBits(width uint) (uint16, error) {
var bits uint16
if r.err == nil {
bits, r.err = r.read(width)
}
}
return bits, r.err
}
 
Line 1,476:
// It does not close the underlying reader.
func (r *Reader) Close() error {
if r.err != nil && r.err != errClosed {
return r.err
}
}
r.err = errClosed
return nil
}
 
// NewReader returns a new bit Reader that reads bytes from `r`.
func NewReader(r io.Reader, order Order) *Reader {
br := new(Reader)
switch order {
case LSB:
br.read = br.readLSB
case MSB:
br.read = br.readMSB
default:
br.err = errors.New("bit writer: unknown order")
return br
}
}
if byteReader, ok := r.(io.ByteReader); ok {
br.r = byteReader
} else {
br.r = bufio.NewReader(r)
}
}
return br
}</lang>
And a test file (such as <code>bit_test.go</code>):
Line 1,506:
 
import (
"bytes"
"fmt"
"io"
"log"
)
 
func ExampleWriter_WriteBits() {
var buf bytes.Buffer
bw := NewWriter(&buf, MSB)
bw.WriteBits(0x0f, 4) // Writes 1111
bw.WriteBits(0x00, 1) // 0
bw.WriteBits(0x13, 5) // 1001 1
// Close will flush with zero bits, in this case
// 0000 00
if err := bw.Close(); err != nil {
log.Fatal(err)
}
}
fmt.Printf("%08b", buf.Bytes())
// Output:
// [11110100 11000000]
}
 
func Example() {
const message = "This is a test."
fmt.Printf("%q as bytes: % 02[1]X\n", message, []byte(message))
fmt.Printf(" original bits: %08b\n", []byte(message))
 
// Re-write in 7 bit chunks to buf:
var buf bytes.Buffer
bw := NewWriter(&buf, MSB)
for _, r := range message {
bw.WriteBits(uint16(r), 7) // nolint: errcheck
}
}
if err := bw.Close(); err != nil {
log.Fatal(err)
}
}
fmt.Printf("Written bitstream: %08b\n", buf.Bytes())
fmt.Printf("Written bytes: % 02X\n", buf.Bytes())
 
// Read back in 7 bit chunks:
br := NewReader(&buf, MSB)
var result []byte
for {
v, err := br.ReadBits(7)
if err != nil {
if err != io.EOF {
log.Fatal(err)
}
}
break
}
}
if v != 0 {
result = append(result, byte(v))
}
}
}
}
fmt.Printf("Read back as \"%s\"\n", result)
// Output:
// "This is a test." as bytes: 54 68 69 73 20 69 73 20 61 20 74 65 73 74 2E
// original bits: [01010100 01101000 01101001 01110011 00100000 01101001 01110011 00100000 01100001 00100000 01110100 01100101 01110011 01110100 00101110]
// Written bitstream: [10101001 10100011 01001111 00110100 00011010 01111001 10100000 11000010 10000011 10100110 01011110 01111101 00010111 00000000]
// Written bytes: A9 A3 4F 34 1A 79 A0 C2 83 A6 5E 7D 17 00
// Read back as "This is a test."
}</lang>
With this test file, running <code>go test -v</code> will compile the package and run the example verifying the output is as listed above in the <code>// Output:</code> comments.
Line 2,030:
my ($out, $l, $num, $q) = @_;
$l .= substr(unpack("B*", pack("N", $num)),
-$q);
if ( (length($l) > 8) ) {
my $left = substr($l, 8);
print $out pack("B8", $l);
$l = $left;
}
return $l;
Line 2,055:
if ( $n > 32 ) { return 0; }
while ( length($b) < $n ) {
my $v;
my $red = read($in, $v, 1);
if ( $red < 1 ) { return ( 0, -1 ); }
$b .= substr(unpack("B*", $v), -8);
}
my $bits = "0" x ( 32-$n ) . substr($b, 0, $n);
Line 2,619:
=={{header|Red}}==
<lang red>Red [
Title: "Bitwise IO"
Link: http://rosettacode.org/wiki/Bitwise_IO
Source: https://github.com/vazub/rosetta-red
File: "%bitwiseio.red"
Rights: "Copyright (C) 2020 Vasyl Zubko. All rights reserved."
License: "Blue Oak Model License - https://blueoakcouncil.org/license/1.0.0"
Tabs: 4
]
 
str-compress: function [
"Compressesor"
str [string!]
][
buf: copy ""
bit-str: enbase/base str 2
foreach [bit1 bit2 bit3 bit4 bit5 bit6 bit7 bit8] bit-str [
append buf rejoin [bit2 bit3 bit4 bit5 bit6 bit7 bit8]
]
]
if (pad-bits: (length? buf) // 8) <> 0 [
loop (8 - pad-bits) [append buf "0"]
]
]
debase/base buf 2
]
 
str-expand: function [
"Decompressor"
bin-hex [binary!]
][
bit-str: enbase/base bin-hex 2
filled: 0
buf: copy []
acc: copy ""
foreach bit bit-str [
append acc bit
filled: filled + 1
if filled = 7 [
append buf debase/base rejoin ["0" acc] 2
clear acc
filled: 0
]
]
]
]
if (last buf) = #{00} [take/last buf]
rejoin buf
]
 
Line 2,669:
expanded: str-expand compressed
prin [
pad "Input (string): " 20 mold in-string newline newline
pad "Input (bits): " 20 enbase/base in-string 2 newline
pad "Compressed (bits): " 20 enbase/base compressed 2 newline newline
pad "Input (hex): " 20 to-binary in-string newline
pad "Compressed (hex): " 20 compressed newline newline
pad "Expanded (string): " 20 mold to-string expanded
]
</lang>
Line 2,788:
puts "fail!"
end</lang>
 
=={{header|Rust}}==
The implementation accepts the number of bits to discard/expand as an argument.
 
<lang Rust>pub trait Codec<Input = u8> {
type Output: Iterator<Item = u8>;
 
fn accept(&mut self, input: Input) -> Self::Output;
fn finish(self) -> Self::Output;
}
 
#[derive(Debug)]
pub struct BitDiscard {
buf: u16, // Use the higher byte for storing the leftovers
buf_bits: u8, // How many bits are valid in the buffer
valid_len: u8, // How many bits to keep from the input
shift_len: u8, // Pre-computed shift of the input byte
}
 
impl BitDiscard {
pub fn new(discard: u8) -> Self {
assert!(discard < 8);
 
BitDiscard {
buf: 0,
buf_bits: 0,
valid_len: 8 - discard,
shift_len: 8 + discard,
}
}
}
 
impl Codec<u8> for BitDiscard {
type Output = std::option::IntoIter<u8>;
 
fn accept(&mut self, input: u8) -> Self::Output {
let add = ((input as u16) << self.shift_len) >> self.buf_bits;
self.buf |= add;
self.buf_bits += self.valid_len;
 
let result = if self.buf_bits >= 8 {
let result = (self.buf >> 8) as u8;
self.buf <<= 8;
self.buf_bits -= 8;
Some(result)
} else {
None
};
 
result.into_iter()
}
 
fn finish(self) -> Self::Output {
let result = if self.buf_bits > 0 {
Some((self.buf >> 8) as u8)
} else {
None
};
 
result.into_iter()
}
}
 
#[derive(Debug)]
pub struct BitExpand {
buf: u16, // For storing the leftovers
buf_bits: u8, // How many bits are valid in the buffer
valid_len: u8, // How many bits are valid in the input
shift_len: u8, // How many bits to shift when expanding
}
 
impl BitExpand {
pub fn new(expand: u8) -> Self {
assert!(expand < 8);
 
Self {
buf: 0,
buf_bits: 0,
valid_len: 8 - expand,
shift_len: 8 + expand,
}
}
}
 
impl Codec<u8> for BitExpand {
type Output = BitExpandIter;
 
fn accept(&mut self, input: u8) -> Self::Output {
let add = ((input as u16) << 8) >> self.buf_bits;
self.buf |= add;
self.buf_bits += 8;
let buf = self.buf;
let leftover = self.buf_bits % self.valid_len;
let buf_bits = self.buf_bits - leftover;
self.buf <<= buf_bits;
self.buf_bits = leftover;
 
Self::Output {
buf,
buf_bits,
shift_len: self.shift_len,
valid_len: self.valid_len,
}
}
 
fn finish(self) -> Self::Output {
Self::Output {
buf: 0,
buf_bits: 0,
shift_len: 0,
valid_len: self.valid_len,
}
}
}
 
#[derive(Debug)]
pub struct BitExpandIter {
buf: u16,
buf_bits: u8,
valid_len: u8,
shift_len: u8,
}
 
impl Iterator for BitExpandIter {
type Item = u8;
 
fn next(&mut self) -> Option<u8> {
if self.buf_bits < self.valid_len {
None
} else {
let result = (self.buf >> self.shift_len) as u8;
self.buf <<= self.valid_len;
self.buf_bits -= self.valid_len;
Some(result)
}
}
}
 
fn process_bytes<C: Codec>(mut codec: C, bytes: &[u8]) -> Vec<u8> {
let mut result: Vec<u8> = bytes.iter().flat_map(|byte| codec.accept(*byte)).collect();
codec.finish().for_each(|byte| result.push(byte));
result
}
 
fn print_bytes(bytes: &[u8]) {
for byte in bytes {
print!("{:08b} ", byte);
}
println!();
 
for byte in bytes {
print!("{:02x} ", byte);
}
println!();
}
 
fn main() {
let original = b"STRINGIFY!";
let discard = 1;
print_bytes(&original[..]);
let compressed = process_bytes(BitDiscard::new(discard), &original[..]);
print_bytes(&compressed);
let decompressed = process_bytes(BitExpand::new(discard), &compressed);
print_bytes(&decompressed);
}</lang>
 
=={{header|Seed7}}==
Anonymous user