bytebits

package module
v0.0.0-...-d8f6b67 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 24, 2021 License: MIT Imports: 3 Imported by: 0

README

This package implements bitwise and bit-field operations on byte slices in the Go language. These are functions that I wish were in the Go standard library's bytes package, or perhaps a subpackage that might be called bytes/bits.

For full API information please see the Godoc documentation.

In brief, the package includes:

  • Insertion and extraction of bit-fields of arbitrary bit widths at arbitrary bit offsets in a byte slice.
  • Insertion and extraction of single bits and fixed-length integers at arbitrary bit offsets in a byte slice.
  • Support for big-endian and (soon) little-endian bit-ordering.
  • Bitwise And, AndNot, Or, Xor, and Not on byte slices.
  • LeadingZeros, TrailingZeros, and OnesCount on byte slices.

I hope you find it useful! Pull requests welcome.

Documentation

Overview

This package provides bit-manipulation and bit-field-manipulation functions that operate on byte slices. It contains functions similar to those the standard 'math/bits' package provides for unsigned integers, but operating on byte slices. Some of this functionality might really belong in the Go standard library, perhaps as a "bytes/bits" sub-package of the current "bytes" package.

This package is preliminary, unstable, and incompletely tested. Beware.

Overview

The And, AndNot, Or, Xor, and Not functions perform the obvious bitwise operations on entire byte slices, either in-place, or into a destination that is allocated or grown as needed. Count counts the total number of zero or one bits in a slice.

The BigEndian and LittleEndian variables are instances of the BigEndianOrder and LittleEndianOrder types, respectively, which provide endianness-dependent bit operations on byte slices. These operations treat byte slices as bit vectors in either big-endian or little-endian bit ordering, as illustrated below.

Big Endian Bit Ordering

To illustrate big-endian bit ordering, a bit-field starting at bit offset 14 and having a width of five bits will contain the least-significant two bits of the second byte and the most-significant three bits of the third byte, as follows:

offset 14 = 8+6 bits            5-bit width
------------------------------> |<------->|
+-----------------+-----------------+-----------------+
| 7 6 5 4 3 2 1 0 | 7 6 5 4 3 2 1 0 | 7 6 5 4 3 2 1 0 |
+-----------------+-----------------+-----------------+

The BigEndian.Uint* and BigEndian.PutUint* operations use big endian as both bit order within bytes and byte order within integers to be read or written at arbitrary positions in a slice.

Little Endian Bit Ordering

To illustrate big-endian bit ordering, a bit-field starting at bit offset 14 and having a width of five bits will contain the most-significant two bits of the second byte and the least-significant three bits of the third byte, as follows:

offset 14 = 8+6 bits            5-bit width
------------------------------> |<------->|
+-----------------+-----------------+-----------------+
| 0 1 2 3 4 5 6 7 | 0 1 2 3 4 5 6 7 | 0 1 2 3 4 5 6 7 |
+-----------------+-----------------+-----------------+

The BigEndian.Uint* and BigEndian.PutUint* operations use big endian as both bit order within bytes and byte order within integers to be read or written at arbitrary positions in a slice.

Limitations

These functions could probably be sped up significantly via architecture-specific optimizations similarly to the math/bits primitives, but this implementation currently does not do so.

Still todo: little endian, shift operations, field Leading/Trailing, more/better testing, bit I/O, ...

Index

Constants

This section is empty.

Variables

View Source
var BigEndian = BigEndianOrder{}

BigEndian instantiates the BitOrder interface for bit-endian bit order.

View Source
var EOF = io.EOF

EOF represents an end-of-File error, and is identical to io.EOF.

Functions

func And

func And(z, x, y []byte) []byte

And sets z to the bitwise AND of slices x and y, and returns z. The source slices x and y must be of the same length. Allocates and returns a new destination slice if z is not long enough.

func AndNot

func AndNot(z, x, y []byte) []byte

AndNot sets z to the bitwise AND of slices x and NOT y, and returns z. The source slices x and y must be of the same length. Allocates and returns a new destination slice if z is not long enough.

func Count

func Count(x []byte, v uint) (n int)

Count returns the number of bits with value v (0 or 1) in slice x.

func Grow

func Grow(z []byte, l int) []byte

Grow grows slice z to have a length of at least l. If z is already of length l or longer, just returns z. If z is shorter but the slice has capacity at least l, returns z[:l]. Otherwise, copies the contents of z to a new slice and returns it.

func Not

func Not(z, x []byte) []byte

Not sets z to the bitwise NOT of slice x, and returns z. Allocates and returns a new destination slice if z is not long enough.

func Or

func Or(z, x, y []byte) []byte

Or sets z to the bitwise OR of slices x and y, and returns z. The source slices x and y must be of the same length. Allocates and returns a new destination slice if z is not long enough.

func Xor

func Xor(z, x, y []byte) []byte

Xor sets z to the bitwise XOR of slices x and y, and returns z. The source slices x and y must be of the same length. Allocates and returns a new destination slice if z is not long enough.

Types

type BigEndianField

type BigEndianField field

BigEndianField represents a bit field within a byte slice interpreted as a big-endian sequence of bits.

func (*BigEndianField) And

func (z *BigEndianField) And(x, y Field) Field

And sets the contents of bit field z to the bitwise AND of fields x and y, and returns z. The source fields x and y must be at least as long as field z.

func (*BigEndianField) AndNot

func (z *BigEndianField) AndNot(x, y Field) Field

AndNot sets the contents of bit field z to the bitwise AND of fields x and NOT y, and returns z. The source fields x and y must be at least as long as field z.

func (*BigEndianField) Count

func (z *BigEndianField) Count(b uint) (n int)

Count returns the number of bits with value b (0 or 1) in field z.

func (*BigEndianField) Fill

func (z *BigEndianField) Fill(b uint)

Fill sets all bits in field z to bit value b (0 or 1).

func (*BigEndianField) Grow

func (z *BigEndianField) Grow(buf []byte, ofs, width int) []byte

Grow points the field to a big-endian bit field within slice buf, copying buf to a new larger buffer if needed to include the bit field. Returns buf or the newly-allocated buffer if it was grown.

func (*BigEndianField) Init

func (z *BigEndianField) Init(buf []byte, ofs, width int) Field

Init sets the field to refer to a big-endian bit field within slice buf, starting at bit offset ofs and extending for width bits. The caller must ensure that the underlying slice is large enough to contain the complete bit field specified; otherwise accesses to the bit field may yield bounds check panics.

func (*BigEndianField) Not

func (z *BigEndianField) Not(x Field) Field

Not sets the contents of bit field z to the bitwise NOT of field x, and returns z. The source field x must be at least as long as field z.

func (*BigEndianField) Or

func (z *BigEndianField) Or(x, y Field) Field

Or sets the contents of bit field z to the bitwise OR of fields x and y, and returns z. The source fields x and y must be at least as long as field z.

func (*BigEndianField) ReadBits

func (z *BigEndianField) ReadBits(n int) (v uint64, err error)

ReadBits implements the BitReader interface, reading up to n bits from the start of the field, or 64 bits maximum. On success, returns the bits read in the least-significant bits of the returned value b, and shrinks the field to skip the n bits read. Returns an EOF error if the bit field is less than n bits wide.

func (*BigEndianField) RotateLeft

func (z *BigEndianField) RotateLeft(x Field, rot int) Field

RotateLeft sets field z to field x rotated left by rot bits. To rotate right, pass a negative value for rot. Field x must be at least as long as z. The slices underlying x and z must not overlap, except if -7 <= rot <= 7, in which case x and z may be identical for small in-place bit rotations.

func (*BigEndianField) Set

func (z *BigEndianField) Set(x Field) Field

Copy sets the contents of bit field z to that of field x, and returns z. The source field x must be at least as long as field z.

func (*BigEndianField) Xor

func (z *BigEndianField) Xor(x, y Field) Field

Xor sets the contents of bit field z to the bitwise XOR of fields x and y, and returns z. The source fields x and y must be at least as long as field z.

type BigEndianOrder

type BigEndianOrder struct{}

BigEndianOrder provides bitwise operations that treat the bits in each byte as having big-endian bit ordering.

You normally invoke its methods via the standard BigEndian instance. For example, to extract the 5-bit field illustrated above, you can invoke:

BigEndian.Bits(dst, src, 14, 5)

BigEndianOrder implements the BitOrder interface for big endian ordering. This interface may be used to parameterize the bit ordering in other code.

func (BigEndianOrder) Bit

func (be BigEndianOrder) Bit(x []byte, xofs int) uint

Bit returns the value of the bit at position xofs bits from the left of x.

func (BigEndianOrder) Copy

func (be BigEndianOrder) Copy(z []byte, x []byte, zofs, xofs, w int) []byte

Copy copies a bit-field of width bits starting at offset xofs in x into a field of the same width starting at offset zofs in z, then returns z. Copies z and returns a new slice if z is null or not large enough. All other bits within z are left unmodified.

func (BigEndianOrder) Field

func (be BigEndianOrder) Field(buf []byte, ofs, width int) Field

func (BigEndianOrder) Leading

func (be BigEndianOrder) Leading(z []byte, b uint) (n int)

Leading counts the number of consecutive leading bits with value b in slice z starting from the most-significant bit of the first byte.

func (BigEndianOrder) PutBit

func (be BigEndianOrder) PutBit(z []byte, zofs int, v uint) []byte

PutBit sets the bit at zofs in slice z to bit value v. Copies z and returns a new slice if z is null or not large enough.

func (BigEndianOrder) PutBytes

func (be BigEndianOrder) PutBytes(z []byte, zofs int, b []byte) []byte

PutBytes writes the contents of byte b slice into slice z at bit offset zofs. Copies z and returns a new slice if z is nil or not large enough.

func (BigEndianOrder) PutUint16

func (be BigEndianOrder) PutUint16(z []byte, zofs int, v uint16) []byte

PutUint16 sets the uint16 starting at zofs in slice z to value v. Copies z and returns a new slice if z is null or not large enough.

func (BigEndianOrder) PutUint32

func (be BigEndianOrder) PutUint32(z []byte, zofs int, v uint32) []byte

PutUint32 sets the uint32 starting at zofs in slice z to value v. Copies z and returns a new slice if z is null or not large enough.

func (BigEndianOrder) PutUint64

func (be BigEndianOrder) PutUint64(z []byte, zofs int, v uint64) []byte

PutUint64 sets the uint64 starting at zofs in slice z to value v. Copies z and returns a new slice if z is null or not large enough.

func (BigEndianOrder) PutUint8

func (be BigEndianOrder) PutUint8(z []byte, zofs int, v uint8) []byte

PutUint8 sets the uint8 starting at zofs in slice z to value v. Copies z and returns a new slice if z is null or not large enough.

func (BigEndianOrder) RotateLeft

func (be BigEndianOrder) RotateLeft(z, x []byte, rot int) []byte

RotateLeft sets slice z to the contents of x rotated left by rot bits. To rotate right, pass a negative value for rot. Copies z and returns a new slice if z is nil or not large enough. The slices x and z must not overlap, except if -8 <= rot <= 8, in which case x and z may be identical for small in-place bit rotations.

func (BigEndianOrder) Trailing

func (be BigEndianOrder) Trailing(z []byte, b uint) (n int)

Trailing counts the number of consecutive trailing bits with value b in slice z starting from the least-significant bit of the last byte.

func (BigEndianOrder) Uint16

func (be BigEndianOrder) Uint16(x []byte, xofs int) uint16

Uint16 extracts a uint16 starting at bit position xofs from the left of x.

func (BigEndianOrder) Uint32

func (be BigEndianOrder) Uint32(x []byte, xofs int) uint32

Uint32 extracts a uint32 starting at bit position xofs from the left of x.

func (BigEndianOrder) Uint64

func (be BigEndianOrder) Uint64(x []byte, xofs int) uint64

Uint64 extracts a uint64 starting at bit position xofs from the left of x.

func (BigEndianOrder) Uint8

func (be BigEndianOrder) Uint8(x []byte, xofs int) uint8

Uint8 extracts a uint8 starting at bit position xofs from the left of x.

type BitReader

type BitReader interface {
	ReadBits(n int) (b uint64, err error)
}

BitReader is an interface to a stream that supports reading a few bits at a time. The ReadBits method reads up to n bits from the stream into the least-significant bits of the returned value b, or reads 64 bits if n > 64. ReadBits returns the number of bits read and any error that occurred; the err return must be non-nil if r != n. Unlike the io.Reader interface, early EOF is considered an error: the BitReader must return EOF if the stream ends before reading n bits. Whether the least- or most-significant bits of the returned value b are treated as coming "first" depends on the endianness of the bit stream.

type BitWriter

type BitWriter interface {
	WriteBits(n int, b uint64) (err error)
}

BitWriter is an interface to a stream that supports writing a few bits at a time.

The WriteBits method writes n bits to the stream from the least-significant bits of b, or writes 64 bits if n > 64. WriteBits returns nil if all n bits were successfully written or an error if not all n bits could be written. Whether WriteBits interprets the least- or most-significant bits of b as coming "first" depends on the endianness of the bit stream.

type Field

type Field interface {
	Set(x Field) Field       // Set to x
	And(x, y Field) Field    // Set to x & y
	AndNot(x, y Field) Field // Set to x &^ y
	Or(x, y Field) Field     // Set to x | y
	Xor(x, y Field) Field    // Set to x ^ y
	Not(x Field) Field       // Set to ^x
	Count(b uint) int        // Count bits with value b
	Fill(b uint)             // Fill with bit value b
	RotateLeft(x Field, rot int) Field
}

Field is an interface to a bit-field providing common bit manipulation operations.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL