bitarray

package module
v1.3.1 Latest Latest
Warning

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

Go to latest
Published: Nov 3, 2021 License: MIT Imports: 19 Imported by: 6

README

go-bitarray

Go Reference MIT License

Overview

Package bitarray provides data types and functions for manipulating bit arrays, aka bit strings, of arbitrary length.

This is designed to handle bit arrays across byte boundaries naturally, without error-prone bitwise operation code such as shifting, masking, and ORing. It may be useful when dealing with Huffman coding, raw packet of various protocols, and binary file formats, etc.

Usage

Manipulate bitarrays using the BitArray type.
import (
	"fmt"
	"github.com/tunabay/go-bitarray"
)

func main() {
	// Parse string representation
	ba1, err := bitarray.Parse("111000")
	if err != nil {
		panic(err)
	}
	fmt.Println(ba1) // 111000

	// Slice and Repeat
	ba2 := ba1.Slice(2, 5).Repeat(2)
	fmt.Println(ba2) // 100100

	// Append
	ba3 := ba2.Append(bitarray.MustParse("101011"))
	// alternative formatting
	fmt.Printf("% b\n", ba3) // 10010010 1011

	// Extract bits from []byte across byte boundary
	buf := []byte{0xff, 0x00}
	ba4 := bitarray.NewFromBytes(buf, 4, 7)
	fmt.Println(ba4) // 1111000
}

Run in Go Playground

Use the Buffer type for bitwise access to byte slices.
import (
	"fmt"
	"github.com/tunabay/go-bitarray"
)

// This example assumes 8-byte data with the following bit layout, and
// accesses the 5-bit integer X and the 50-bit integer Y in it.
//
// |0              |1              |2              |3              |
// |0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | 9-bit flag area | 5-bit X | Upper 18 bits of the 50-bit int Y |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// |               Lower 32 bits of the 50-bit int Y               |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
func main() {
	data := make([]byte, 8)
	buf := bitarray.NewBufferFromByteSlice(data)

	// set 9-bit flag area to 110000011
	buf.PutBitAt(0, 1)
	buf.PutBitAt(1, 1)
	buf.PutBitAt(7, 1)
	buf.PutBitAt(8, 1)

	// set 5-bit integer X
	buf.Slice(9, 14).PutUint8(25) // = 0b_11001

	// set 50-bit integer Y
	buf.Slice(14, 64).PutUint64(0x_3_f0ff_f0f0_ff0f)

	// raw bytes updated
	fmt.Printf("%08b\n%08b\n", data[:4], data[4:])

	// read fields
	fmt.Printf("F = %b\n", buf.Slice(0, 9))
	fmt.Printf("X = %d\n", buf.Slice(9, 14).Uint8())
	fmt.Printf("Y = %x\n", buf.SliceToEnd(14).Uint64())
}

Run in Go Playground

Documentation and more examples

License

go-bitarray is available under the MIT license. See the LICENSE file for more information.

Documentation

Overview

Package bitarray provides data types and functions for manipurating bit arrays, aka bit strings, of arbitrary number of bits.

Example (BitArray)
// Parse string representation
ba1, err := bitarray.Parse("111000")
if err != nil {
	panic(err)
}
fmt.Println(ba1)

// Slice and Repeat
ba2 := ba1.Slice(2, 5).Repeat(2)
fmt.Println(ba2)

// Append
ba3 := ba2.Append(bitarray.MustParse("101011"))
fmt.Printf("% b\n", ba3) // alternative formatting

// Extract bits from []byte across byte boundary
buf := []byte{0xff, 0x00}
ba4 := bitarray.NewFromBytes(buf, 4, 7)
fmt.Println(ba4)
Output:

111000
100100
10010010 1011
1111000
Example (BitLayout)
// This example assumes 8-byte data with the following bit layout, and
// accesses the 5-bit integer X and the 50-bit integer Y in it.
//
//   |0              |1              |2              |3              |
//   |0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|
//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//   | 9-bit flag area | 5-bit X | Upper 18 bits of the 50-bit int Y |
//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//   |               Lower 32 bits of the 50-bit int Y               |
//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
data := make([]byte, 8)
buf := bitarray.NewBufferFromByteSlice(data)

// set 9-bit flag area to 110000011
buf.PutBitAt(0, 1)
buf.PutBitAt(1, 1)
buf.PutBitAt(7, 1)
buf.PutBitAt(8, 1)

// set 5-bit integer X
buf.Slice(9, 14).PutUint8(25) // = 0b_11001

// set 50-bit integer Y
buf.Slice(14, 64).PutUint64(0x_3_f0ff_f0f0_ff0f)

// raw bytes updated
fmt.Printf("%08b\n%08b\n", data[:4], data[4:])

// read fields
fmt.Printf("F = %b\n", buf.Slice(0, 9))
fmt.Printf("X = %d\n", buf.Slice(9, 14).Uint8())
fmt.Printf("Y = %x\n", buf.SliceToEnd(14).Uint64())
Output:

[11000001 11100111 11110000 11111111]
[11110000 11110000 11111111 00001111]
F = 110000011
X = 25
Y = 3f0fff0f0ff0f

Index

Examples

Constants

This section is empty.

Variables

View Source
var BreakIteration = errors.New("break iteration")

BreakIteration is used as a return value from IterateFunc to indicate the current iteration is to be terminated without error.

View Source
var ErrFractionalBitsBeforeEOF = errors.New("fractional bits before EOF")

ErrFractionalBitsBeforeEOF is an error thrown when a byte-oriented reading method reaches io.EOF but there are still fractional bits less than 8 bits that cannot be read in bytes.

View Source
var ErrIllegalExpression = errors.New("illegal bit array expression")

ErrIllegalExpression is an error thrown when a string representation of bit array is not a legal format.

Functions

func Compare

func Compare(x, y BitArrayer) int

Compare returns an integer comparing two bit arrays lexicographically. The result will be 0 if x == y, -1 if x < y, and +1 if y < x. A nil argument is equivalent to an empty bit array.

Example
x := bitarray.MustParse("11100010 1100111")
y := bitarray.MustParse("11100010 100")
fmt.Println(bitarray.Compare(x, y))
fmt.Println(bitarray.Compare(y, x))
fmt.Println(bitarray.Compare(x, x))
Output:

1
-1
0

func CopyBits added in v1.2.0

func CopyBits(dst, src *Buffer) int

CopyBits copies bits from src into dst. CopyBits returns the number of bits copied, which will be the minimum of src.Len() and dst.Len().

Example
ba := bitarray.MustParse("1100-1010 0001")
bufSrc := bitarray.NewBufferFromBitArray(ba)
bufDstL := bitarray.NewBuffer(18)
bufDstS := bitarray.NewBuffer(7)

bitarray.CopyBits(bufDstL, bufSrc)
fmt.Println(bufDstL)
bitarray.CopyBits(bufDstS, bufSrc)
fmt.Println(bufDstS)
Output:

110010100001000000
1100101

func CopyBitsN added in v1.2.0

func CopyBitsN(dst, src *Buffer, nBits int) int

CopyBitsN is identical to CopyBits except that it copies up to nBits bits.

Example
ba := bitarray.MustParse("1100-1010 1111")
bufSrc := bitarray.NewBufferFromBitArray(ba)
bufDstL := bitarray.NewBuffer(18)
bufDstS := bitarray.NewBuffer(7)

bitarray.CopyBitsN(bufDstL, bufSrc, 10)
fmt.Println(bufDstL)
bitarray.CopyBitsN(bufDstS, bufSrc, 10)
fmt.Println(bufDstS)
Output:

110010101100000000
1100101

func CopyBitsPartial added in v1.2.0

func CopyBitsPartial(dst, src *Buffer, dstOff, srcOff, nBits int) int

CopyBitsPartial is identical to CopyBitsN except that it reads and writes bits starting at specified offsets rather than the first bits.

Example
ba := bitarray.MustParse("1101-1110 0011")
bufSrc := bitarray.NewBufferFromBitArray(ba)
bufDst := bitarray.NewBuffer(18)

bitarray.CopyBitsPartial(bufDst, bufSrc, 10, 3, 4)
fmt.Println(bufDst)
Output:

000000000011110000

Types

type Alignment

type Alignment bool

Alignment is used in some bitwise operations to specify whether the bits are left-aligned or right-aligned. The zero value is AlignLeft.

const (
	AlignLeft  Alignment = false
	AlignRight Alignment = true
)

func (Alignment) String

func (a Alignment) String() string

String returns the string representation of Alignment.

type BitArray

type BitArray struct {
	// contains filtered or unexported fields
}

BitArray represents an immutable bit array, or a sequence of bits, of arbitrary length. Unlike the builtin []byte, BitArray can properly hold and handle fractional bits less than 8 bits. The zero value for BitArray represents an empty bit array of zero length. Since it is immutable, it can be shared, copied and is safe for concurrent use by multiple goroutines.

func Join

func Join(elems []*BitArray, sep BitArrayer) *BitArray

Join concatenates the elements of its first parameter to create a single bit array. The separator sep is placed between elements in the result.

Example
elems := []*bitarray.BitArray{
	bitarray.MustParse("10101"),
	bitarray.MustParse("111"),
	bitarray.MustParse("1"),
	bitarray.MustParse("1111111111"),
}
sep := bitarray.MustParse("00000")
ba := bitarray.Join(elems, sep)
fmt.Printf("% s\n", ba)
Output:

10101000 00111000 00100000 11111111 11

func JoinBitArrayer

func JoinBitArrayer(elems []BitArrayer, sep BitArrayer) *BitArray

JoinBitArrayer is identical to Join except that it accepts elems in []BitArrayer type instead of []*BitArray type.

Example
elems := []bitarray.BitArrayer{
	bitarray.MustParse("10101"),
	bitarray.MustParse("111"),
	bitarray.MustParse("1"),
	bitarray.MustParse("1111111111"),
}
sep := bitarray.MustParse("00000")
ba := bitarray.JoinBitArrayer(elems, sep)
fmt.Printf("% s\n", ba)
Output:

10101000 00111000 00100000 11111111 11

func MustParse

func MustParse(s string) *BitArray

MustParse is like Parse but panics if the expression can not be parsed. It simplifies safe initialization of global variables holding bit arrays.

Example
ba := bitarray.MustParse("1100-1111 1010-0000 1111")
fmt.Println(ba)
Output:

11001111101000001111

func New

func New(bits ...byte) *BitArray

New creates and returns a new BitArray instance from the bits passed as parameters. Each parameter should be 0 or 1, but if any other value is passed, no error is reported and only the LSB of each is silently used. In most cases it is more convenient to use Parse, NewFromBytes or other functions instead of New.

Example
ba := bitarray.New(0, 0, 1, 1, 0, 1)
fmt.Printf("%s\n", ba)
Output:

001101

func NewByRunLength

func NewByRunLength(lengths ...int) *BitArray

NewByRunLength creates a BitArray with the argument that represents the number of consecutive 0 and 1 bits. The (2n+1)th arguments including the first specifies the length of 0s, and the (2n)th arguments including the second specifies the length of 1s. Passing 0 as the first argument allows to create a bit array starting with 1. It is suitable for making simple bit masks.

Example
ba1 := bitarray.NewByRunLength(1, 2, 3, 4, 5, 6)
ba2 := bitarray.NewByRunLength(0, 1, 1, 2, 3, 5, 8, 13)
fmt.Printf("% b\n", ba1)
fmt.Printf("% b\n", ba2)
Output:

01100011 11000001 11111
10110001 11110000 00001111 11111111 1

func NewFromByteBits

func NewFromByteBits(bits []byte) *BitArray

NewFromByteBits creates a new BitArray from a []byte in which each element represents 1 bit as 0 or 1. If an element is neighter 0 nor 1, only its LSB is silently used.

Example
bits := []byte{0, 1, 1, 0, 0, 0, 1, 1, 1, 1}
ba := bitarray.NewFromByteBits(bits)
fmt.Printf("% b\n", ba)
Output:

01100011 11

func NewFromBytes

func NewFromBytes(p []byte, off, nBits int) *BitArray

NewFromBytes reads bits from a byte slice b, creates a new BitArray instance and returns it. It skips off bits from the beginning of p and reads nBits bits from the next bit.

Example
b := []byte{0b_1010_1111, 0b_0101_0011}
ba := bitarray.NewFromBytes(b, 2, 12)
fmt.Printf("% b\n", ba)
Output:

10111101 0100

func NewFromInt

func NewFromInt(v *big.Int) *BitArray

NewFromInt creates a BitArray from big.Int. The returned bit array represents the absolute value of v in big-endian byte order. For big.Int(0), it returns a "0" instead of an empty bit array.

Example
v := big.NewInt(1234567890123456)
ba := bitarray.NewFromInt(v)
fmt.Printf("% s\n", ba)
Output:

10001100 01011010 10100111 10010001 01010111 01011000 000

func NewOneFilled

func NewOneFilled(nBits int) *BitArray

NewOneFilled creates a BitArray with all digits filled with 1.

Example
ba := bitarray.NewOneFilled(28)
fmt.Printf("% b\n", ba)
Output:

11111111 11111111 11111111 1111

func NewZeroFilled

func NewZeroFilled(nBits int) *BitArray

NewZeroFilled creates a BitArray with all digits filled with 0. An all zero filled bit array does not allocate memory for 0 bits. If all bits in a bit array are guaranteed to be 0, using this function saves memory usage and optimizes some bitwise operations.

Example
ba := bitarray.NewZeroFilled(42)
fmt.Printf("% b\n", ba)
Output:

00000000 00000000 00000000 00000000 00000000 00

func Parse

func Parse(s string) (*BitArray, error)

Parse parses a string as a bit array representation, like "01010".

Multiple tokens can be presented, which are separated by one or more spaces and/or a single "+" sign. All bits contained in tokens will be simply concatenated. Each token can be binary, octal, or hexademical, and the type is specified by the prefixes "0b", "0o" or "0x". Tokens without a prefix are always parsed as binary representation. Each token also can contain any number of separators "-", "_", and ":". These separators are safely ignored.

Note that spaces between digits are parsed as token delimiters, not separators within tokens. This is not a problem for binary representations, but "0o" and "0x" prefixes have no effect beyond the spaces. For example, "0b0000 1111" is legal, but "0x0000 ffff" is illegal. Because the "ffff" is interpreted as a second token without a prefix, so "f" cannot be parsed as binary representation. Use other separators instead: e.g. "0x0000_ffff".

bitarray  = *WSP [ token *( token-sep token ) ] *WSP
token-sep = *WSP ( WSP / "+" ) *WSP
token     = bin-token / oct-token / hex-token
bin-token = [ "0b" [ char-sep ] ] bin-char *( [ char-sep ] bin-char )
oct-token = "0o" 1*( [ char-sep ] oct-char ) [ oct-pad ]
hex-token = "0x" 1*( [ char-sep ] hex-char ) [ hex-pad ]
char-sep  = "-" / "_" / ":"
bin-char  = "0" / "1"
oct-char  = bin-char / "2" / "3" / "4" / "5" / "6" / "7"
hex-char  = oct-char / "8" / "9"
          / "a" / "b" / "c" / "d" / "e" / "f"
          / "A" / "B" / "C" / "D" / "E" / "F"
oct-pad   = [ " " ] "(" pad-ind ( "0" / "1" / "2" )       ")"
hex-pad   = [ " " ] "(" pad-ind ( "0" / "1" / "2" / "3" ) ")"
pad-ind   = "pad=" / "!"
Example
baB, err := bitarray.Parse("0101-0101 1111-1111 1101-11")
if err != nil {
	fmt.Println(err)
}
fmt.Printf("% s\n", baB)

baH, err := bitarray.Parse("0x_ff88_7")
if err != nil {
	fmt.Println(err)
}
fmt.Printf("% s\n", baH)

baO, err := bitarray.Parse("0o0777")
if err != nil {
	fmt.Println(err)
}
fmt.Printf("% s\n", baO)
Output:

01010101 11111111 110111
11111111 10001000 0111
00011111 1111
Example (MultipleTokens)
ba, err := bitarray.Parse("00000 + 0xfff + 0b_000 + 0o775")
if err != nil {
	fmt.Println(err)
}
fmt.Printf("% s\n", ba)
Output:

00000111 11111111 10001111 11101
Example (PaddingBits)
ba0, _ := bitarray.Parse("0xfc0")
ba1, _ := bitarray.Parse("0xfc0 (pad=1)")
ba2, _ := bitarray.Parse("0xfc0 (pad=2)")
ba3, _ := bitarray.Parse("0xfc0 (pad=3)")
fmt.Printf("% s\n", ba0)
fmt.Printf("% s\n", ba1)
fmt.Printf("% s\n", ba2)
fmt.Printf("% s\n", ba3)
Output:

11111100 0000
11111100 000
11111100 00
11111100 0

func PseudoRand

func PseudoRand(nBits int, gen *rand.Rand) *BitArray

PseudoRand generates a random bit array with nBits length. If gen is non-nil, it will be used as the source instead of the default source. In this case, it is not safe for concurrent use by multiple goroutines. Only the default source is safe for concurrent use.

This is based on math/rand package, and not cryptographically secure. Use Rand for security-sensitive data.

Note that even generating less than 8 bits consumes 1 byte from the source. Therefore, the results are different between the case where 4 bits are generated twice and concatenated, and the case where 8 bits are generated at once, even in the same source state.

Example
rand.Seed(1234)

ba := bitarray.PseudoRand(42, nil)
fmt.Printf("% s\n", ba)
Output:

11000000 00001110 01011101 01100111 11000010 01
Example (CustomSource)
myRand := rand.New(rand.NewSource(1234))

ba0 := bitarray.PseudoRand(42, myRand)
ba1 := bitarray.PseudoRand(13, myRand)
fmt.Printf("% s\n", ba0)
fmt.Printf("% s\n", ba1)
Output:

11000000 00001110 01011101 01100111 11000010 01
01010011 10001

func Rand

func Rand(nBits int) (*BitArray, error)

Rand generates a random bit array with nBits length.

This is based on the crypto/rand package and cryptographically secure.

Example
ba, err := bitarray.Rand(42)
if err != nil {
	panic(err)
}

fmt.Printf("% s\n", ba)

func (*BitArray) AllIndex

func (ba *BitArray) AllIndex(x BitArrayer) []int

AllIndex returns the indexes of the all instance of x in the bit array ba, or empty slice if x is not present in ba.

Example
haystack := bitarray.MustParse("0010-1011 0001-0101 0101-0111 111")
needle := bitarray.MustParse("1010")

fmt.Println(haystack.AllIndex(needle))
Output:

[2 11 13 15 17]

func (*BitArray) And

func (ba *BitArray) And(x BitArrayer) *BitArray

And returns a new BitArray as a result of a bitwise AND with x. The ba and x must be the same length, otherwise And will panic. Use AndAt instead to apply a partial AND with a short bit array.

Example
ba1 := bitarray.MustParse("1111-0000 0011-01")
ba2 := bitarray.MustParse("1010-1010 1010-10")
fmt.Printf("% b\n", ba1.And(ba2))
Output:

10100000 001000

func (*BitArray) AndAt

func (ba *BitArray) AndAt(off int, x BitArrayer) *BitArray

AndAt returns a new BitArray resulting from applying a bitwise AND operation with x at the offset off. AND is applied only to the range from off to off+x.Len(), and other bits are preserved.

Example
ba1 := bitarray.MustParse("1010-1010 1010-1010 10")
ba2 := bitarray.MustParse("1111-0000")
fmt.Printf("% b\n", ba1.AndAt(0, ba2))
fmt.Printf("% b\n", ba1.AndAt(4, ba2))
fmt.Printf("% b\n", ba1.AndAt(10, ba2))
Output:

10100000 10101010 10
10101010 00001010 10
10101010 10101000 00

func (*BitArray) Append

func (ba *BitArray) Append(bas ...BitArrayer) *BitArray

Append returns the new BitArray resulting from appending the passed elements to the current bit array.

Example
ba1 := bitarray.MustParse("110011")
ba2 := bitarray.MustParse("00000000 0000")
ba3 := bitarray.MustParse("111")
fmt.Printf("% s\n", ba1.Append(ba2, ba3))
fmt.Printf("% s\n", ba2.Append(nil))
fmt.Printf("% s\n", ba3.Append(ba3, ba3, ba3))
Output:

11001100 00000000 00111
00000000 0000
11111111 1111

func (*BitArray) BitArray

func (ba *BitArray) BitArray() *BitArray

BitArray implements the BitArrayer interface returning itself.

func (*BitArray) BitAt

func (ba *BitArray) BitAt(off int) byte

BitAt returns a single bit at the specified offset as 0 or 1. It panics if the off is negative or greater than ba.Len()-1.

Example
ba := bitarray.MustParse("10001000 10")
fmt.Println(ba.BitAt(0), ba.BitAt(4), ba.BitAt(8))
Output:

1 1 1

func (*BitArray) Bytes

func (ba *BitArray) Bytes() ([]byte, int)

Bytes returns the byte slice containing the bit array. It also returns the number of the padded LSBs.

Example
ba := bitarray.MustParse("11111111 00000000 1110")
bs, npad := ba.Bytes()
fmt.Printf("%x, npad=%d\n", bs, npad)
Output:

ff00e0, npad=4

func (*BitArray) Equal

func (ba *BitArray) Equal(x BitArrayer) bool

Equal returns whether the bit array is the same as specified one. nil and zero length bit array are considered to be equal.

Example
ba1 := bitarray.MustParse("1100-0010 001")
ba2 := bitarray.MustParse("0011-1101 110")
fmt.Println(ba1.Equal(ba2))
fmt.Println(ba1.Equal(ba2.Not()))
Output:

false
true

func (BitArray) Format

func (ba BitArray) Format(s fmt.State, verb rune)

Format implements the fmt.Formatter interface to format BitArray values using the standard fmt.Printf family functions.

Verbs:

%b, %s  binary, 1 digit represents 1 bit.
%q      quoted version of %b.
%v      default format, same as %b.
%o      octal, 1 digit represents 3 bits.
%x, %X  hexadecimal, 1 digit represents 4 bits.

Flags:

' '     (space) print a separator space every 8 digits.
#       more separators, ' ' and/or '-' every 4 digits.
-       left-justify
+       print the number of padding bits at the end, for %o, %x, %X
Example (Printf)
ba := bitarray.MustParse("1111-0000 1010-0011 111")

fmt.Printf("%b\n", ba)      // 1111000010100011111
fmt.Printf("% b\n", ba)     // 11110000 10100011 111
fmt.Printf("%#b\n", ba)     // 1111-0000 1010-0011 111
fmt.Printf("%o\n", ba)      // 7412174
fmt.Printf("%+x\n", ba)     // f0a3e(pad=1)
fmt.Printf("%q\n", ba)      // "1111000010100011111"
fmt.Printf("[%24b]\n", ba)  // [     1111000010100011111]
fmt.Printf("[%-24b]\n", ba) // [1111000010100011111     ]
Output:

1111000010100011111
11110000 10100011 111
1111-0000 1010-0011 111
7412174
f0a3e(pad=1)
"1111000010100011111"
[     1111000010100011111]
[1111000010100011111     ]

func (*BitArray) HasPrefix

func (ba *BitArray) HasPrefix(prefix BitArrayer) bool

HasPrefix reports whether the bit array starts with prefix.

Example
ba := bitarray.MustParse("1010-1111 0000-1111 10")

fmt.Println(ba.HasPrefix(bitarray.MustParse("10101")))
fmt.Println(ba.HasPrefix(bitarray.MustParse("111")))
Output:

true
false

func (*BitArray) HasSuffix

func (ba *BitArray) HasSuffix(suffix BitArrayer) bool

HasSuffix reports whether the bit array ends with suffix.

Example
ba := bitarray.MustParse("1010-1111 0000-1111 10")

fmt.Println(ba.HasSuffix(bitarray.MustParse("11110")))
fmt.Println(ba.HasSuffix(bitarray.MustParse("111")))
Output:

true
false

func (*BitArray) Hash deprecated

func (ba *BitArray) Hash(h hash.Hash) []byte

Hash calculates the hash of the bit array using the hash function h. The hash.Hash is designed to accept input in bytes instead of bits. This causes problems with bit arrays that have padding LSBs at the end. For example, the two bit arrays "1111" and "1111000" would both be represented as the same single byte 0xf0. In order to prevent these from being mapped to the same hash value, the hash is calculated after appending a 3 bits marker indicating the number of padding LSBs at the end of the original bit array.

Deprecated: Most hash functions can handle bit-oriented messages as-is by design, and it is not appropriate to use the byte-oriented standard hash.Hash with padding bits. The result does not comply with the specifications. Not all hash functions are available, but for SHA-1 and SHA-2, which can handle bit-oriented messages correctly, dedicated methods such as SHA512, SHA256, and SHA1 are now available. It is better to use them instead.

Example (Md5)
ba1 := bitarray.MustParse("11111110 11111111 0000")
ba2 := bitarray.MustParse("11111111 11111111 0000")
ba3 := bitarray.MustParse("11111111 11111111 00000")
fmt.Printf("%x\n", ba1.Hash(md5.New()))
fmt.Printf("%x\n", ba2.Hash(md5.New()))
fmt.Printf("%x\n", ba3.Hash(md5.New()))
Output:

734a8ff2ae91df5975e32c95cf83d88e
2241281d24ea5e99500ff0b2f925709e
9f51432b4c47d144039b8259564bb89b
Example (Sha256)
ba1 := bitarray.MustParse("11111110 11111111 0000")
ba2 := bitarray.MustParse("11111111 11111111 0000")
ba3 := bitarray.MustParse("11111111 11111111 00000")
fmt.Printf("%x\n", ba1.Hash(sha256.New()))
fmt.Printf("%x\n", ba2.Hash(sha256.New()))
fmt.Printf("%x\n", ba3.Hash(sha256.New()))
Output:

9c5dfdfd1abe7dc4c5018ed54f338bc1c7e9ec70769cd37bda4e826d389f8ba0
42f0862649c6f51d8aaa31d810d9c2e4455917b61b0b17f13fbd66007cb6d75e
074d99c983072816cbc8d980c4a2fd441f6036aca06f83ee14e05cab5afbed85

func (*BitArray) Index

func (ba *BitArray) Index(x BitArrayer) int

Index returns the index of the first instance of x in the bit array ba, or -1 if x is not present in ba.

Example
haystack := bitarray.MustParse("0010-1011 0001-0101 0101-0111 111")
needle := bitarray.MustParse("1010")

fmt.Println(haystack.Index(needle))
Output:

2

func (*BitArray) IsZero

func (ba *BitArray) IsZero() bool

IsZero returns whether the BitArray is empty, zero length.

Example
ba1 := bitarray.MustParse("")
ba2 := bitarray.MustParse("0")
ba3 := bitarray.MustParse("00000000")
fmt.Println(ba1.IsZero())
fmt.Println(ba2.IsZero())
fmt.Println(ba3.IsZero())
Output:

true
false
false

func (*BitArray) Iterate

func (ba *BitArray) Iterate(fn IterateFunc) error

Iterate iterates calling the function fn for each bit in order from the beginning of the bit array. Iterate returns an error only if the function fn returns an error that is not BreakIteration. Otherwise, it returns nil after calling fn for the last bit.

Example
ba := bitarray.MustParse("1111 0101 0000")

fn := func(i, b int) error {
	fmt.Printf("%d: %d\n", i, b)
	if i == 10 {
		return bitarray.BreakIteration
	}
	return nil
}
if err := ba.Iterate(fn); err != nil {
	panic(err)
}
Output:

0: 1
1: 1
2: 1
3: 1
4: 0
5: 1
6: 0
7: 1
8: 0
9: 0
10: 0
Example (Error)
ba := bitarray.MustParse("000010")

fn := func(i, b int) error {
	if b == 1 {
		return fmt.Errorf("unexpected bit 1 at %d", i)
	}
	fmt.Printf("%d: %d\n", i, b)
	return nil
}
if err := ba.Iterate(fn); err != nil {
	fmt.Printf("got error: %s\n", err)
}
Output:

0: 0
1: 0
2: 0
3: 0
got error: unexpected bit 1 at 4

func (*BitArray) LastIndex

func (ba *BitArray) LastIndex(x BitArrayer) int

LastIndex returns the index of the last instance of x in the bit array ba, or -1 if x is not present in ba.

Example
haystack := bitarray.MustParse("0010-1011 0001-0101 0101-0111 111")
needle := bitarray.MustParse("1010")

fmt.Println(haystack.LastIndex(needle))
Output:

17

func (*BitArray) LeadingZeros

func (ba *BitArray) LeadingZeros() int

LeadingZeros returns the number of leading zero bits in the BitArray.

Example
ba1 := bitarray.MustParse("1000-0111 0100")
ba2 := bitarray.MustParse("0000-0000 0000-1100 0110-1")
ba3 := bitarray.MustParse("0000-0")

fmt.Println(ba1.LeadingZeros())
fmt.Println(ba2.LeadingZeros())
fmt.Println(ba3.LeadingZeros())
Output:

0
12
5

func (*BitArray) Len

func (ba *BitArray) Len() int

Len returns the number of bits contained in the BitArray.

Example
ba1 := bitarray.MustParse("1111-0000 1111-0000 111")
ba2 := bitarray.MustParse("101")
ba3 := bitarray.MustParse("")
fmt.Println(ba1.Len())
fmt.Println(ba2.Len())
fmt.Println(ba3.Len())
Output:

19
3
0

func (*BitArray) MapKey

func (ba *BitArray) MapKey() string

MapKey returns a string that can be used as a key for the Go built-in map. Only the same bit array returns the same string. The String method can also be used for the same purpose, but MapKey is faster. Note that it can be used as a map key, but it may contain non-printable characters.

Example
ba1 := bitarray.MustParse("1010-1100 0")
ba2 := bitarray.MustParse("1010-1100 00")
ba3 := bitarray.MustParse("")

m := make(map[string]string)
m[ba1.MapKey()] = "ba1"
m[ba2.MapKey()] = "ba2"
m[ba3.MapKey()] = "ba3"

for k, v := range m {
	fmt.Printf("%q -> %s\n", k, v)
}
Output:

"\x01\xac\x00" -> ba1
"\x02\xac\x00" -> ba2
"" -> ba3

func (*BitArray) MarshalBinary

func (ba *BitArray) MarshalBinary() ([]byte, error)

MarshalBinary implements the standard encoding.BinaryMarshaler interface to marshal a BitArray into a binary form.

This appends 0 to 7 bits padding followed by 3 bits marker indicating the actual number of padding LSBs at the end of the original bit array.

| nBits&7 | last two bytes    mark | pad |
+---------+-----------+------------+-----+
|       5 | 1111 1111 | 1111 1:000 |   3 |
|       4 | 1111 1111 | 1111 -:001 |   4 |
|       3 | 1111 1111 | 111- -:010 |   5 |
|       2 | 1111 1111 | 11-- -:011 |   6 |
|       1 | 1111 1111 | 1--- -:100 |   7 |
|       0 | 1111 1111 | ---- -:101 |   8 |
|       7 | 1111 111- | ---- -:110 |   9 |
|       6 | 1111 11-- | ---- -:111 |  10 |
Example
ba := bitarray.MustParse("1111-0101 11")

bin, _ := ba.MarshalBinary()
fmt.Printf("%x\n", bin)
Output:

f5c3

func (*BitArray) MarshalJSON

func (ba *BitArray) MarshalJSON() ([]byte, error)

MarshalJSON implements the standard json.Marshaler interface to marshal a BitArray into a JSON form. This always returns a nil error.

Example
data := &struct {
	Foo  *bitarray.BitArray `json:"foox"`
	Bar  *bitarray.BitArray
	Baz  *bitarray.BitArray
	Qux  *bitarray.BitArray
	List []*bitarray.BitArray
}{
	Foo: bitarray.MustParse("1111-0000 111"),
	Bar: bitarray.MustParse("0000-0000"),
	Baz: bitarray.MustParse(""),
	List: []*bitarray.BitArray{
		bitarray.MustParse("0001"),
		bitarray.MustParse("1000"),
	},
}

out, err := json.MarshalIndent(data, "", "  ")
if err != nil {
	panic(err)
}

fmt.Println(string(out))
Output:

{
  "foox": "11110000111",
  "Bar": "00000000",
  "Baz": "",
  "Qux": null,
  "List": [
    "0001",
    "1000"
  ]
}

func (*BitArray) MarshalText

func (ba *BitArray) MarshalText() ([]byte, error)

MarshalText implements the standard encoding.TextMarshaler interface to marshal a BitArray into a textual form. This always returns a nil error.

Example
ba := bitarray.MustParse("1111-0101 11")

txt, _ := ba.MarshalText()
fmt.Printf("%s\n", txt)
Output:

1111010111

func (*BitArray) MarshalYAML

func (ba *BitArray) MarshalYAML() (interface{}, error)

MarshalYAML implements the yaml.Marshaler.

Example
data := &struct {
	Foo  *bitarray.BitArray `yaml:"foox"`
	Bar  *bitarray.BitArray
	Baz  *bitarray.BitArray
	Qux  *bitarray.BitArray
	List []*bitarray.BitArray
}{
	Foo: bitarray.MustParse("1111-0000 111"),
	Bar: bitarray.MustParse("0000-0000"),
	Baz: bitarray.MustParse(""),
	List: []*bitarray.BitArray{
		bitarray.MustParse("0001"),
		bitarray.MustParse("1000"),
	},
}

out, err := yaml.Marshal(data)
if err != nil {
	panic(err)
}

fmt.Println(string(out))
Output:

foox: "11110000111"
bar: "00000000"
baz: ""
qux: null
list:
    - "0001"
    - "1000"

func (*BitArray) Not

func (ba *BitArray) Not() *BitArray

Not returns a new BitArray that is the result of inverting all the bits.

Example
ba := bitarray.MustParse("1111-0000 1010")
fmt.Printf("% b\n", ba.Not())
Output:

00001111 0101

func (*BitArray) NumPadding

func (ba *BitArray) NumPadding() int

NumPadding returns the number of LSBs padded when expressing the bit array as []byte type, that is, the number of bits to be added to make it a multiple of 8 bits.

Example
ba1 := bitarray.MustParse("11110000 11110000")
ba2 := bitarray.MustParse("11110000 11110000 000")
ba3 := bitarray.MustParse("11110000 11110000 000000")
fmt.Println(ba1.NumPadding())
fmt.Println(ba2.NumPadding())
fmt.Println(ba3.NumPadding())
Output:

0
5
2

func (*BitArray) OnesCount

func (ba *BitArray) OnesCount() int

OnesCount returns the number of one bits, population count, in the BitArray.

Example
ba1 := bitarray.MustParse("1100-1100 11")
ba2 := bitarray.MustParse("0000-0000 0000-10")
ba3 := bitarray.MustParse("0000")
fmt.Println(ba1.OnesCount())
fmt.Println(ba2.OnesCount())
fmt.Println(ba3.OnesCount())
Output:

6
1
0

func (*BitArray) Or

func (ba *BitArray) Or(x BitArrayer) *BitArray

Or returns a new BitArray as a result of a bitwise OR with x. The ba and x must be the same length, otherwise Or will panic. Use OrAt instead to apply a partial OR with a short bit array.

Example
ba1 := bitarray.MustParse("1111-0000 0011-01")
ba2 := bitarray.MustParse("1010-1010 1010-10")
fmt.Printf("% b\n", ba1.Or(ba2))
Output:

11111010 101111

func (*BitArray) OrAt

func (ba *BitArray) OrAt(off int, x BitArrayer) *BitArray

OrAt returns a new BitArray resulting from applying a bitwise OR operation with x at the offset off. OR is applied only to the range from off to off+x.Len(), and other bits are preserved.

Example
ba1 := bitarray.MustParse("1010-1010 1010-1010 10")
ba2 := bitarray.MustParse("1111-0000")
fmt.Printf("% b\n", ba1.OrAt(0, ba2))
fmt.Printf("% b\n", ba1.OrAt(4, ba2))
fmt.Printf("% b\n", ba1.OrAt(10, ba2))
Output:

11111010 10101010 10
10101111 10101010 10
10101010 10111110 10

func (*BitArray) ParityBit

func (ba *BitArray) ParityBit() int

ParityBit calculates the odd parity bit of the bit array.

Example
ba1 := bitarray.MustParse("0000-000")
ba2 := bitarray.MustParse("1010-001")
ba3 := bitarray.MustParse("1111-111")
fmt.Println(ba1.ParityBit())
fmt.Println(ba2.ParityBit())
fmt.Println(ba3.ParityBit())
Output:

1
0
0

func (*BitArray) Repeat

func (ba *BitArray) Repeat(count int) *BitArray

Repeat returns a bit array consisting of count copies of the bit array ba.

Example
ba := bitarray.MustParse("111000")
fmt.Printf("% s\n", ba.Repeat(5))
fmt.Printf("% s\n", ba.Repeat(1))
fmt.Printf("% q\n", ba.Repeat(0))
Output:

11100011 10001110 00111000 111000
111000
""

func (*BitArray) RepeatEach

func (ba *BitArray) RepeatEach(count int) *BitArray

RepeatEach returns a new BitArray in which each bit is repeated the specified number of times. It is an operation like "scaling" a bit pattern.

Example
ba := bitarray.MustParse("0101-0011 001")
fmt.Printf("% b\n", ba.RepeatEach(2))
fmt.Printf("% b\n", ba.RepeatEach(3))
fmt.Printf("[% b]\n", ba.RepeatEach(0))
Output:

00110011 00001111 000011
00011100 01110000 00111111 00000011 1
[]

func (*BitArray) Reverse

func (ba *BitArray) Reverse() *BitArray

Reverse returns the bit array with its bits in reversed order.

Example
ba := bitarray.MustParse("1100-1111 0000-1010")

fmt.Printf("% b\n", ba.Reverse())
Output:

01010000 11110011

func (*BitArray) RotateLeft

func (ba *BitArray) RotateLeft(k int) *BitArray

RotateLeft returns the bit array of rotated left by k bits. To rotate to right, call RotateLeft(-k).

Example
ba := bitarray.MustParse("1100-1111 0000-1010 11")

fmt.Printf("% b\n", ba.RotateLeft(1))
fmt.Printf("% b\n", ba.RotateLeft(8))
fmt.Printf("% b\n", ba.RotateLeft(-5))
fmt.Printf("% b\n", ba.RotateLeft(0))
Output:

10011110 00010101 11
00001010 11110011 11
01011110 01111000 01
11001111 00001010 11

func (*BitArray) SHA1 added in v1.1.0

func (ba *BitArray) SHA1() [20]byte

SHA1 returns the SHA-1 checksum of the bit array. It treats the bit array as a bit-oriented message to compute the checksum as defined in RFC 3174.

Example
ba1 := bitarray.MustParse("01")
ba2 := bitarray.MustParse("01001")

fmt.Printf("%x\n", ba1.SHA1())
fmt.Printf("%x\n", ba2.SHA1())
Output:

ec6b39952e1a3ec3ab3507185cf756181c84bbe2
3320540d1c28b96ddd03eee1b186a8f2ae883fbe

func (*BitArray) SHA224 added in v1.1.0

func (ba *BitArray) SHA224() (d224 [28]byte)

SHA224 returns the SHA-224 checksum of the bit array. It treats the bit array as a bit-oriented message to compute the checksum as defined in FIPS 180-4.

Example
ba1 := bitarray.MustParse("10")
ba2 := bitarray.MustParse("100")

fmt.Printf("%x\n", ba1.SHA224())
fmt.Printf("%x\n", ba2.SHA224())
Output:

ef9c947a47bb9311a0f2b8939cfc12090554868b3b64d8f71e6442f3
4f2ec61c914dce56c3fe5067aa184125ab126c39edb8bf64f58bdccd

func (*BitArray) SHA256 added in v1.1.0

func (ba *BitArray) SHA256() (d256 [32]byte)

SHA256 returns the SHA-256 checksum of the bit array. It treats the bit array as a bit-oriented message to compute the checksum as defined in FIPS 180-4.

Example
ba1 := bitarray.MustParse("011")
ba2 := bitarray.MustParse("010000")

fmt.Printf("%x\n", ba1.SHA256())
fmt.Printf("%x\n", ba2.SHA256())
Output:

1f7794d4b0b67d3a6edcd17aba2144a95828032f7943ed26bf0c7c7628945f48
5ef0224f79737bda30562831152184b939cc43fcd40d09f4945e081a39c6d542

func (*BitArray) SHA384 added in v1.1.0

func (ba *BitArray) SHA384() (d384 [48]byte)

SHA384 returns the SHA-384 checksum of the bit array. It treats the bit array as a bit-oriented message to compute the checksum as defined in FIPS 180-4.

Example
ba1 := bitarray.MustParse("0")
ba2 := bitarray.MustParse("00")

fmt.Printf("%x\n", ba1.SHA384())
fmt.Printf("%x\n", ba2.SHA384())
Output:

634aa63038a164ae6c7d48b319f2aca0a107908e548519204c6d72dbeac0fdc3c9246674f98e8fd30221ba986e737d61
c6b08368812f4f02aaf84c1b8fcd549f53099816b212fe68cb32f6d73563fae8cec52b96051ade12ba8f3c6a6e98a616

func (*BitArray) SHA512 added in v1.1.0

func (ba *BitArray) SHA512() (d512 [64]byte)

SHA512 returns the SHA-512 checksum of the bit array. It treats the bit array as a bit-oriented message to compute the checksum as defined in FIPS 180-4.

Example
ba1 := bitarray.MustParse("01")
ba2 := bitarray.MustParse("0100000")

fmt.Printf("%x\n", ba1.SHA512())
fmt.Printf("%x\n", ba2.SHA512())
Output:

a726c0deb12ba0c375cc75ec974f567c08c8d921d78fc8d0a05bfc644d0730ea5716970f2006b4599264d4145dc579b118113ffa1690040e4d98ed2d3450e923
acec0655565de641ff3185c686798c1428026673fe2b5deef309987bc991df2b5dadcccfc4eeafe99ff57c97188427e98edafe30bca3f4e4139fd33a9dd6bf79

func (*BitArray) SHA512_224 added in v1.1.0

func (ba *BitArray) SHA512_224() (d224 [28]byte)

SHA512_224 returns the SHA-512/224 checksum of the bit array. It treats the bit array as a bit-oriented message to compute the digest as defined in FIPS 180-4.

func (*BitArray) SHA512_256 added in v1.1.0

func (ba *BitArray) SHA512_256() (d256 [32]byte)

SHA512_256 returns the SHA-512/256 checksum of the bit array. It treats the bit array as a bit-oriented message to compute the checksum as defined in FIPS 180-4.

Example
{ //nolint: govet // false positive for _256 suffix
	ba1 := bitarray.MustParse("0000")
	ba2 := bitarray.MustParse("00000")

	fmt.Printf("%x\n", ba1.SHA512_256())
	fmt.Printf("%x\n", ba2.SHA512_256())

	
Output:

d164616e829e534122e34d48492b66ce4d4fb39fff688880a67e646c0a98f6ab
849eb77bcea6b85ab720b3788ff4b0c04896e26b902d9040edeebfbd190fc8dd

func (*BitArray) ShiftLeft

func (ba *BitArray) ShiftLeft(k int) *BitArray

ShiftLeft returns the bit array of shifted left by k bits. To shift to right, call ShiftLeft(-k).

Example
ba := bitarray.MustParse("1100-1111 0000-1010 11")

fmt.Printf("% b\n", ba.ShiftLeft(1))
fmt.Printf("% b\n", ba.ShiftLeft(8))
fmt.Printf("% b\n", ba.ShiftLeft(-5))
fmt.Printf("% b\n", ba.ShiftLeft(0))
Output:

10011110 00010101 10
00001010 11000000 00
00000110 01111000 01
11001111 00001010 11

func (*BitArray) Slice

func (ba *BitArray) Slice(start, end int) *BitArray

Slice returns a new BitArray extracted as a subpart from the bit array in the same manner as Go's native slices. The two arguments start and end specify the indexes of the bits to select. 0 points to the first bit and ba.Len()-1 points to the last bit. The start and end select a half-open range which includes the start, but excludes the end. If the index is outside the range of the bit array, Slice will panic.

Example
ba := bitarray.MustParse("0011-1010 0110-1111 110")
fmt.Printf("% s\n", ba.Slice(4, 14))
fmt.Printf("% s\n", ba.Slice(9, 13))
Output:

10100110 11
1101

func (*BitArray) SliceToEnd added in v1.2.0

func (ba *BitArray) SliceToEnd(start int) *BitArray

SliceToEnd is shorthand for Slice(start, ba.Len()) and returns the subpart from the position specified start to the last bit.

Example
ba := bitarray.MustParse("0011-1010 01101")
fmt.Printf("% b\n", ba.SliceToEnd(4))
fmt.Printf("% b\n", ba.SliceToEnd(9))
Output:

10100110 1
1101

func (BitArray) String

func (ba BitArray) String() string

String returns the string representation of the BitArray.

Example
ba := bitarray.MustParse("0000-1111 0000-1111 0000-1")
fmt.Printf("%s\n", ba.String())
fmt.Println(ba)
Output:

000011110000111100001
000011110000111100001

func (*BitArray) ToByteBits

func (ba *BitArray) ToByteBits() []byte

ToByteBits returns a byte slice that represents the bit array with 1 byte per bit. Each byte element of the returned slice represents a single bit with 0 or 1. It is a memory-wasting data type, but for the purpose of repeating searches and matching using the same bit array, converting to this format allows the standard bytes package to be used.

Example
ba1 := bitarray.MustParse("101010")
ba2 := bitarray.MustParse("0000-1111 1111")
fmt.Printf("%d\n", ba1.ToByteBits())
fmt.Printf("%d\n", ba2.ToByteBits())
Output:

[1 0 1 0 1 0]
[0 0 0 0 1 1 1 1 1 1 1 1]

func (*BitArray) ToInt

func (ba *BitArray) ToInt() *big.Int

ToInt parses the bit array as a big-endian representation, and convert it to an unsigned integer value. The leading 0s have no effect on the result.

Example
ba := bitarray.MustParse("00001001 00110010 11000000 01011010 010")
fmt.Println(ba.ToInt())
Output:

1234567890

func (*BitArray) ToPadded64

func (ba *BitArray) ToPadded64() *BitArray

ToPadded64 returns a new BitArray with a length that is a multiple of 64 bits by apending 0 to 63 padding bits at the end. For the returned bit array, NumPadding() returns 0, and Len() returns a multiple of 8.

Example
ba1 := bitarray.MustParse("1111-11")
ba2 := bitarray.MustParse("0x_ffff_ffff_ffff")
fmt.Printf("% x\n", ba1.ToPadded64())
fmt.Printf("% x\n", ba2.ToPadded64())
Output:

fc000000 00000000
ffffffff ffff0000

func (*BitArray) ToPadded8

func (ba *BitArray) ToPadded8() *BitArray

ToPadded8 returns a new BitArray with a length that is a multiple of 8 bits by apending 0 to 7 padding bits at the end. For the returned bit array, NumPadding() returns 0.

Example
ba1 := bitarray.MustParse("1111")
ba2 := bitarray.MustParse("1111-1111 1")
ba3 := bitarray.MustParse("1111-1111 1111-1111")
fmt.Printf("% b\n", ba1.ToPadded8())
fmt.Printf("% b\n", ba2.ToPadded8())
fmt.Printf("% b\n", ba3.ToPadded8())
Output:

11110000
11111111 10000000
11111111 11111111

func (*BitArray) ToUint64

func (ba *BitArray) ToUint64() uint64

ToUint64 is the same as ToInt except that it returns uint64 instead of *big.Int. If the bit array length exceeds 64 bits, only the last 64 bits will be used.

Example
ba := bitarray.MustParse("10010011 00101100 00000101 10111010 10")
fmt.Println(ba.ToUint64())
Output:

9876543210

func (*BitArray) ToWidth

func (ba *BitArray) ToWidth(wid int, align Alignment) *BitArray

ToWidth returns a new BitArray resized to wid bits with its contents preserved. If wid is less than ba.Len(), some bits will be lost. If wid is greater than be.Len(), the expanded space will be filled with 0s. In both cases, the MSBs or LSBs are fixed according to the specified align.

Example
ba := bitarray.MustParse("1010-1111 0000-11")
fmt.Printf("% s\n", ba.ToWidth(7, bitarray.AlignLeft))
fmt.Printf("% s\n", ba.ToWidth(7, bitarray.AlignRight))
fmt.Printf("% s\n", ba.ToWidth(20, bitarray.AlignLeft))
fmt.Printf("% s\n", ba.ToWidth(20, bitarray.AlignRight))
Output:

1010111
1000011
10101111 00001100 0000
00000010 10111100 0011

func (*BitArray) TrailingZeros

func (ba *BitArray) TrailingZeros() int

TrailingZeros returns the number of trailing zero bits in the BitArray.

Example
ba1 := bitarray.MustParse("1100-1111 1100-0000 0000-0")
ba2 := bitarray.MustParse("0000-0001 1111")
ba3 := bitarray.MustParse("000")

fmt.Println(ba1.TrailingZeros())
fmt.Println(ba2.TrailingZeros())
fmt.Println(ba3.TrailingZeros())
Output:

11
0
3

func (*BitArray) TrimLeadingZeros

func (ba *BitArray) TrimLeadingZeros() *BitArray

TrimLeadingZeros returns a new BitArray with the leading zeros removed.

Example
ba1 := bitarray.MustParse("0000-0010 1100-11")
ba2 := bitarray.MustParse("1000-0000 0")
ba3 := bitarray.MustParse("0000-0000 0000-0000 0000")
fmt.Printf("% s\n", ba1.TrimLeadingZeros())
fmt.Printf("% s\n", ba2.TrimLeadingZeros())
fmt.Printf("[% s]\n", ba3.TrimLeadingZeros())
Output:

10110011
10000000 0
[]

func (*BitArray) TrimPrefix

func (ba *BitArray) TrimPrefix(prefix BitArrayer) *BitArray

TrimPrefix returns a new BitArray with the leading prefix removed. If the bit array does not start with prefix, ba itself is returned unchanged.

Example
ba1 := bitarray.MustParse("1010-1011 0011-0011 01")
ba2 := bitarray.MustParse("1010-1111 1111")
ba3 := bitarray.MustParse("1010-10")
prefix := bitarray.MustParse("1010-10")
fmt.Printf("% s\n", ba1.TrimPrefix(prefix))
fmt.Printf("% s\n", ba2.TrimPrefix(prefix))
fmt.Printf("[% s]\n", ba3.TrimPrefix(prefix))
Output:

11001100 1101
10101111 1111
[]

func (*BitArray) TrimSuffix

func (ba *BitArray) TrimSuffix(suffix BitArrayer) *BitArray

TrimSuffix returns a new BitArray with the trailing suffix removed. If the bit array does not end with prefix, ba itself is returned unchanged.

Example
ba1 := bitarray.MustParse("1010-1011 0011-00")
ba2 := bitarray.MustParse("1111-1000 11")
ba3 := bitarray.MustParse("1100")
suffix := bitarray.MustParse("1100")
fmt.Printf("% s\n", ba1.TrimSuffix(suffix))
fmt.Printf("% s\n", ba2.TrimSuffix(suffix))
fmt.Printf("[% s]\n", ba3.TrimSuffix(suffix))
Output:

10101011 00
11111000 11
[]

func (*BitArray) TrimTrailingZeros

func (ba *BitArray) TrimTrailingZeros() *BitArray

TrimTrailingZeros returns a new BitArray with the trailing zeros removed.

Example
ba1 := bitarray.MustParse("1010-0110 000")
ba2 := bitarray.MustParse("0000-0000 01")
ba3 := bitarray.MustParse("0000-0000 0000-0000 0000")
fmt.Printf("% s\n", ba1.TrimTrailingZeros())
fmt.Printf("% s\n", ba2.TrimTrailingZeros())
fmt.Printf("[% s]\n", ba3.TrimTrailingZeros())
Output:

1010011
00000000 01
[]

func (*BitArray) Xor

func (ba *BitArray) Xor(x BitArrayer) *BitArray

Xor returns a new BitArray as a result of a bitwise XOR with x. The ba and x must be the same length, otherwise Xor will panic. Use XorAt instead to apply a partial XOR with a short bit array.

Example
ba1 := bitarray.MustParse("1111-0000 0011-01")
ba2 := bitarray.MustParse("1010-1010 1010-10")
fmt.Printf("% b\n", ba1.Xor(ba2))
Output:

01011010 100111

func (*BitArray) XorAt

func (ba *BitArray) XorAt(off int, x BitArrayer) *BitArray

XorAt returns a new BitArray resulting from applying a bitwise XOR operation with x at the offset off. XOR is applied only to the range from off to off+x.Len(), and other bits are preserved.

Example
ba1 := bitarray.MustParse("1010-1010 1010-1010 10")
ba2 := bitarray.MustParse("1111-0000")
fmt.Printf("% b\n", ba1.XorAt(0, ba2))
fmt.Printf("% b\n", ba1.XorAt(4, ba2))
fmt.Printf("% b\n", ba1.XorAt(10, ba2))
Output:

01011010 10101010 10
10100101 10101010 10
10101010 10010110 10

type BitArrayer

type BitArrayer interface {
	BitArray() *BitArray
}

BitArrayer is an interface implemented by any type that can be treated as a BitArray. Within this package, BitArray itself, Builder and Buffer implement this interface.

BitArray returns the value of itself converted to a BitArray. Note that for non-immutable types, multiple calls may return different values. It is legal to return nil to represent an empty BitArray, and it should be treated the same as a zero-length BitArray.

type Buffer

type Buffer struct {
	// contains filtered or unexported fields
}

Buffer is a bit array buffer whose contents can be updated by partial reading and writing with an offset. It is not safe for concurrent use by multiple goroutines. The zero value for Buffer represents a zero length buffer that can be resized and used.

Example
buf := bitarray.NewBuffer(32)
fmt.Println(buf)
buf.PutBitAt(0, 1)
buf.PutBitAt(1, 1)
fmt.Println(buf)
buf.PutBitArrayAt(8, bitarray.MustParse("1010101"))
fmt.Println(buf)
buf.FillBitsAt(16, 4, 1)
fmt.Println(buf)
buf.PutBitArrayAt(24, bitarray.MustParse("1111-0000"))
fmt.Println(buf)
buf.ToggleBitsAt(24, 8)
fmt.Println(buf)

fmt.Printf("% b\n", buf.BitArray())
Output:

00000000000000000000000000000000
11000000000000000000000000000000
11000000101010100000000000000000
11000000101010101111000000000000
11000000101010101111000011110000
11000000101010101111000000001111
11000000 10101010 11110000 00001111

func NewBuffer

func NewBuffer(nBits int) *Buffer

NewBuffer creates a Buffer with the specified bit length.

Example
buf0 := bitarray.NewBuffer(0)
buf64 := bitarray.NewBuffer(64)

fmt.Println(buf0)
fmt.Println(buf64)
Output:

0000000000000000000000000000000000000000000000000000000000000000

func NewBufferFromBitArray

func NewBufferFromBitArray(ba BitArrayer) *Buffer

NewBufferFromBitArray creates a new Buffer with the same bit length and initial content as the specified BitArray.

Example
ba := bitarray.MustParse("1111-1111 0000-0000 1111-1111")
buf := bitarray.NewBufferFromBitArray(ba)

fmt.Println(buf)
Output:

111111110000000011111111

func NewBufferFromByteSlice added in v1.2.0

func NewBufferFromByteSlice(b []byte) *Buffer

NewBufferFromByteSlice creates a new Buffer that references an existing byte slice b. The created Buffer references b without copying it, therefore, changes to the buffer affect b and vice versa. The length of the buffer created will be len(b) * 8. NewBufferFromByteSlice is useful when reading or writing a subpart of a byte slice as a bit array without copying or bit-shifting.

Example
b := []byte{0b_0000_1111, 0b_1111_0000}
buf := bitarray.NewBufferFromByteSlice(b)

fmt.Printf("b=%08b, buf=% b\n", b, buf)
buf.PutBitAt(0, 1)
buf.PutBitAt(15, 1)
fmt.Printf("b=%08b, buf=% b\n", b, buf)
Output:

b=[00001111 11110000], buf=00001111 11110000
b=[10001111 11110001], buf=10001111 11110001

func NewBufferFromByteSlicePartial added in v1.2.0

func NewBufferFromByteSlicePartial(b []byte, off, nBits int) *Buffer

NewBufferFromByteSlicePartial is identical to NewBufferFromByteSlice except that it creates a buffer with the first bit specified by off, and the length specified by nBits.

Example
b := []byte{0b_0000_1111, 0b_1111_0000}
buf := bitarray.NewBufferFromByteSlicePartial(b, 4, 6)

fmt.Printf("b=%08b, buf=%b\n", b, buf)
buf.PutBitAt(0, 0)
buf.PutBitAt(1, 0)
buf.PutBitAt(5, 0)
fmt.Printf("b=%08b, buf=%b\n", b, buf)
Output:

b=[00001111 11110000], buf=111111
b=[00000011 10110000], buf=001110

func (*Buffer) AndAt

func (buf *Buffer) AndAt(off int, x BitArrayer)

AndAt applies a bitwise AND operation with x at the offset off. AND is applied only to the range from off to off+x.Len(), and other bits are preserved.

Example
ba := bitarray.MustParse("11110000")
buf := bitarray.NewBufferFromBitArray(ba)

fmt.Println(buf)
buf.AndAt(2, bitarray.MustParse("0110"))
fmt.Println(buf)
Output:

11110000
11010000

func (*Buffer) BitArray

func (buf *Buffer) BitArray() *BitArray

BitArray creates an imuurable BitArray from the current content.

func (*Buffer) BitArrayAt

func (buf *Buffer) BitArrayAt(off, nBits int) *BitArray

BitArrayAt returns bits within the specified range as a BitArray.

Example
ba := bitarray.MustParse("1100-1010 0000-1111")
buf := bitarray.NewBufferFromBitArray(ba)

fmt.Println(buf.BitArrayAt(0, 6))
fmt.Println(buf.BitArrayAt(4, 10))
Output:

110010
1010000011

func (*Buffer) BitAt

func (buf *Buffer) BitAt(off int) byte

BitAt returns a single bit at the specified offset as 0 or 1. It panics if the off is out of range.

Example
ba := bitarray.MustParse("1100-10")
buf := bitarray.NewBufferFromBitArray(ba)

fmt.Println(buf.BitAt(0))
fmt.Println(buf.BitAt(3))
fmt.Println(buf.BitAt(5))
Output:

1
0
0

func (*Buffer) ByteAt

func (buf *Buffer) ByteAt(off int) byte

ByteAt reads 8 bits starting at the offset off and returns them as a single byte. Note that off is in bits, not bytes. If the off is not a multiple of 8, 8 bits across a byte boundary are returned.

Example
ba := bitarray.MustParse("1100-1010 0011-1111")
buf := bitarray.NewBufferFromBitArray(ba)

fmt.Printf("%08b\n", buf.ByteAt(2))
fmt.Printf("%08b\n", buf.ByteAt(6))
Output:

00101000
10001111

func (*Buffer) Bytes added in v1.2.0

func (buf *Buffer) Bytes() []byte

Bytes returns all the bits of the buffer as a byte slice. If buf.Len() is not a multiple of 8, it will be padded with 0.

Example
ba := bitarray.MustParse("1100-1010 1010-1111 0101-11")
buf := bitarray.NewBufferFromBitArray(ba)

fmt.Printf("%08b\n", buf.Bytes())
fmt.Printf("%08b\n", buf.Slice(4, 20).Bytes())
Output:

[11001010 10101111 01011100]
[10101010 11110101]

func (*Buffer) BytesAt

func (buf *Buffer) BytesAt(off, nBytes int) []byte

BytesAt reads 8 * nBytes bits starting at the offset off and returns them as a byte slice. Note that off is in bits, not bytes. If the off is not a multiple of 8, it returns a properly shifted byte slice.

Example
ba := bitarray.MustParse("1100-1010 0011-1111 1010-0000 0111-1000")
buf := bitarray.NewBufferFromBitArray(ba)

fmt.Printf("%08b\n", buf.BytesAt(2, 3))
fmt.Printf("%08b\n", buf.BytesAt(12, 2))
Output:

[00101000 11111110 10000001]
[11111010 00000111]

func (*Buffer) Clone

func (buf *Buffer) Clone() *Buffer

Clone clones the Buffer with its content.

func (*Buffer) CopyBitsFromBytes added in v1.2.0

func (buf *Buffer) CopyBitsFromBytes(off int, b []byte, bOff, nBits int)

CopyBitsFromBytes reads nBits bits from b at the offset bOff, and write them into the buffer at the offset off.

Example
ba := bitarray.MustParse("1100-1010 0001-0011 1010-00")
buf := bitarray.NewBufferFromBitArray(ba)

fmt.Println(buf)
buf.CopyBitsFromBytes(2, []byte{0xff, 0x00}, 6, 4)
fmt.Println(buf)
buf.CopyBitsFromBytes(6, []byte{0xAA, 0xFF, 0xAA}, 4, 16)
fmt.Println(buf)
Output:

1100101000010011101000
1111001000010011101000
1111001010111111111010

func (*Buffer) CopyBitsToBytes added in v1.2.0

func (buf *Buffer) CopyBitsToBytes(off int, b []byte, bOff, nBits int)

CopyBitsToBytes reads nBits bits of the buffer starting at the offset off, and write them into the byte slice b at the offset bOff.

Example
ba := bitarray.MustParse("1100-1010 0001")
buf := bitarray.NewBufferFromBitArray(ba)

b := make([]byte, 3)

buf.CopyBitsToBytes(0, b, 0, 12)
fmt.Printf("%08b\n", b)

buf.CopyBitsToBytes(4, b, 16, 4)
buf.CopyBitsToBytes(4, b, 20, 4)
fmt.Printf("%08b\n", b)
Output:

[11001010 00010000 00000000]
[11001010 00010000 10101010]

func (*Buffer) FillBits added in v1.2.0

func (buf *Buffer) FillBits(bit byte)

FillBits sets all the bits in the buffer to the value bit, 0 or 1.

Example
buf := bitarray.NewBuffer(12)

buf.Slice(5, 10).FillBits(1)
fmt.Printf("% b\n", buf)
Output:

00000111 1100

func (*Buffer) FillBitsAt

func (buf *Buffer) FillBitsAt(off, nBits int, bit byte)

FillBitsAt sets the nBits bits starting at off to the value bit.

func (Buffer) Format

func (buf Buffer) Format(s fmt.State, verb rune)

Format implements the fmt.Formatter interface to format Buffer value using the standard fmt.Printf family functions.

func (*Buffer) IsZero

func (buf *Buffer) IsZero() bool

IsZero returns whether the Buffer is zero length.

func (*Buffer) LeadingZeros

func (buf *Buffer) LeadingZeros() int

LeadingZeros returns the number of leading zero bits in the Buffer.

Example
ba := bitarray.MustParse("11110000")
buf := bitarray.NewBufferFromBitArray(ba)

fmt.Printf("%b: %d\n", buf, buf.LeadingZeros())
buf.ToggleBitsAt(0, 2)
fmt.Printf("%b: %d\n", buf, buf.LeadingZeros())
Output:

11110000: 0
00110000: 2

func (*Buffer) Len

func (buf *Buffer) Len() int

Len returns the number of bits contained in the buffer.

Example
buf := bitarray.NewBuffer(4096)

fmt.Println(buf.Len())
Output:

4096

func (*Buffer) OnesCount

func (buf *Buffer) OnesCount() int

OnesCount returns the number of one bits, population count, in the Buffer.

Example
ba := bitarray.MustParse("00111100")
buf := bitarray.NewBufferFromBitArray(ba)

fmt.Printf("%b: %d\n", buf, buf.OnesCount())
buf.ToggleBitsAt(0, 6)
fmt.Printf("%b: %d\n", buf, buf.OnesCount())
Output:

00111100: 4
11000000: 2

func (*Buffer) OrAt

func (buf *Buffer) OrAt(off int, x BitArrayer)

OrAt applies a bitwise OR operation with x at the offset off. OR is applied only to the range from off to off+x.Len(), and other bits are preserved.

Example
ba := bitarray.MustParse("11110000")
buf := bitarray.NewBufferFromBitArray(ba)

fmt.Println(buf)
buf.OrAt(2, bitarray.MustParse("0110"))
fmt.Println(buf)
Output:

11110000
11111000

func (*Buffer) PutBitArrayAt

func (buf *Buffer) PutBitArrayAt(off int, ba BitArrayer)

PutBitArrayAt writes bits from a BitArray onto the specified offset off.

Example
ba := bitarray.MustParse("1111-0000 0000-1111")
buf := bitarray.NewBufferFromBitArray(ba)

fmt.Println(buf)
buf.PutBitArrayAt(2, bitarray.MustParse("0101"))
buf.PutBitArrayAt(10, bitarray.MustParse("0000"))
buf.PutBitArrayAt(6, bitarray.MustParse("1111"))
fmt.Println(buf)
Output:

1111000000001111
1101011111000011

func (*Buffer) PutBitAt

func (buf *Buffer) PutBitAt(off int, bit byte)

PutBitAt writes a single bit at the position specified by off in the buffer. The bit should be 0 or 1, otherwise its LSB is silently used.

Example
ba := bitarray.MustParse("11110000")
buf := bitarray.NewBufferFromBitArray(ba)

fmt.Println(buf)
buf.PutBitAt(0, 0)
buf.PutBitAt(1, 1)
buf.PutBitAt(7, 1)
fmt.Println(buf)
Output:

11110000
01110001

func (*Buffer) PutByteAt

func (buf *Buffer) PutByteAt(off int, b byte)

PutByteAt writes 8 bits of b to the position specified by off in the buffer. Note that off is in bits, not bytes. If the off is not a multiple of 8, it writes 8 bits across a byte boundary.

Example
ba := bitarray.MustParse("0000-1010 0011-11")
buf := bitarray.NewBufferFromBitArray(ba)

fmt.Println(buf)
buf.PutByteAt(2, 0xff)
fmt.Println(buf)
buf.PutByteAt(6, 0x00)
fmt.Println(buf)
Output:

00001010001111
00111111111111
00111100000000

func (*Buffer) PutBytesAt

func (buf *Buffer) PutBytesAt(off int, b []byte)

PutBytesAt writes 8 * len(b) bits of b to the position specified by off in the buffer. Note that off is in bits, not bytes. If the off is not a multiple of 8, it writes bytes across byte boundaries of the buffer.

Example
ba := bitarray.MustParse("1100-1010 0011-1111 1010-0000 0111-1000")
buf := bitarray.NewBufferFromBitArray(ba)

fmt.Println(buf)
buf.PutBytesAt(2, []byte{0x00, 0x00, 0x00})
fmt.Println(buf)
buf.PutBytesAt(6, []byte{0xAA, 0xFF, 0xAA})
fmt.Println(buf)
Output:

11001010001111111010000001111000
11000000000000000000000000111000
11000010101010111111111010101000

func (*Buffer) PutUint16 added in v1.3.0

func (buf *Buffer) PutUint16(v uint16)

PutUint16 sets a uint16 value v within up to 16 bits from the beginning of the buffer. If buf.Len() is greater than 16, only the first 16 bits are updated. If buf.Len() is less than 16, only the LSBs of v are written.

Example
b := make([]byte, 3)
buf := bitarray.NewBufferFromByteSlice(b)

buf.Slice(4, 20).PutUint16(0xffff)
fmt.Printf("%08b\n", b)
buf.Slice(10, 16).PutUint16(0b1010)
fmt.Printf("%08b\n", b)
Output:

[00001111 11111111 11110000]
[00001111 11001010 11110000]

func (*Buffer) PutUint32 added in v1.3.0

func (buf *Buffer) PutUint32(v uint32)

PutUint32 sets a uint32 value v within up to 32 bits from the beginning of the buffer. If buf.Len() is greater than 32, only the first 32 bits are updated. If buf.Len() is less than 32, only the LSBs of v are written.

Example
b := make([]byte, 5)
buf := bitarray.NewBufferFromByteSlice(b)

buf.Slice(4, 36).PutUint32(0xff00ffff)
fmt.Printf("%08b\n", b)
buf.Slice(16, 28).PutUint32(0xf0c)
fmt.Printf("%08b\n", b)
Output:

[00001111 11110000 00001111 11111111 11110000]
[00001111 11110000 11110000 11001111 11110000]

func (*Buffer) PutUint64 added in v1.3.0

func (buf *Buffer) PutUint64(v uint64)

PutUint64 sets a uint64 value v within up to 64 bits from the beginning of the buffer. If buf.Len() is greater than 64, only the first 64 bits are updated. If buf.Len() is less than 64, only the LSBs of v are written.

Example
b := make([]byte, 9)
buf := bitarray.NewBufferFromByteSlice(b)

buf.Slice(4, 68).PutUint64(0x1234567812345678)
fmt.Printf("%x\n", b)
buf.Slice(12, 24).PutUint64(0xabc)
fmt.Printf("%x\n", b)
Output:

012345678123456780
012abc678123456780

func (*Buffer) PutUint8 added in v1.3.0

func (buf *Buffer) PutUint8(v uint8)

PutUint8 sets a uint8 value v within up to 8 bits from the beginning of the buffer. If buf.Len() is greater than 8, only the first 8 bits are updated. If buf.Len() is less than 8, only the LSBs of v are written.

Example
b := make([]byte, 2)
buf := bitarray.NewBufferFromByteSlice(b)

buf.Slice(4, 12).PutUint8(255) // 11111111
fmt.Printf("%08b\n", b)
buf.Slice(0, 6).PutUint8(42)   // 101010
buf.SliceToEnd(13).PutUint8(7) // 111
fmt.Printf("%08b\n", b)
Output:

[00001111 11110000]
[10101011 11110111]

func (*Buffer) RawBytes added in v1.2.0

func (buf *Buffer) RawBytes() []byte

RawBytes returns all the bits of the buffer as a byte slice. The caller must not change the contents of the returned byte slice. The slice returned may or may not reference to the internal buffer itself of buf, depending on whether bit-shifting is needed of not. Also, if buf.Len() is not a multiple of 8, the bits after the last bit in the slice returned are undefined. The main purpose of RawBytes is to efficiently pass bit data to other byte-oriented APIs. In general, it is recommended to use the safer Bytes() instead.

Example
ba := bitarray.MustParse("1111-0000 1010-1010 1111-1111 11")
buf := bitarray.NewBufferFromBitArray(ba)

// not byte-aligned, copied, 0-padded
fmt.Printf("%08b\n", buf.Slice(3, 24).RawBytes())
// byte-aligned, not copied, not 0-padded
fmt.Printf("%08b\n", buf.Slice(3, 24).Slice(5, 16).RawBytes())
Output:

[10000101 01010111 11111000]
[10101010 11111111]

func (*Buffer) Resize

func (buf *Buffer) Resize(nBits int, align Alignment)

Resize resizes the Buffer to the size specified by nBits. When expanding, all bits in the new range to be extended are initialized with 0. When shrinking, the extra bits are truncated. In either case, the align specifies whether to fix the MSBs or the LSBs.

Resize always reallocates internal memory. That is, the buffers created by Slice method or NewBufferFromByteSlice break their relationship with the parent buffer or slice by calling this Resize, even if nBits is equivalent to or less than its current size.

func (*Buffer) Slice added in v1.2.0

func (buf *Buffer) Slice(start, end int) *Buffer

Slice extracts a subpart from the buffer and returns it as a new Buffer in the same manner as Go's native slices. Note that like Go's native slices, the sliced buffers share memory with the original buffer. Changes to the original buffer affect slices and vice versa. Slice does not perform bit-shifting, even when creating slices that are not aligned to byte boundaries. It just records the offset and length for reference.

The two arguments start and end specify the indexes of the bits to select. 0 points to the first bit and buf.Len()-1 points to the last bit. The start and end select a half-open range which includes the start, but excludes the end. If the index is outside the range of the buffer, Slice will panic.

Example
ba := bitarray.MustParse("0011-1010 0110-1111 110")
buf := bitarray.NewBufferFromBitArray(ba)

buf2 := buf.Slice(4, 14)
fmt.Println(buf2)
buf3 := buf.Slice(9, 13)
fmt.Println(buf3)
Output:

1010011011
1101
Example (Update)
ba := bitarray.MustParse("1000-0000 0000-01")
buf := bitarray.NewBufferFromBitArray(ba)

sub := buf.Slice(6, 10)
fmt.Println(buf, sub)

sub.FillBitsAt(0, 4, 1)
fmt.Println(buf, sub)

buf.FillBitsAt(7, 2, 0)
fmt.Println(buf, sub)
Output:

10000000000001 0000
10000011110001 1111
10000010010001 1001

func (*Buffer) SliceToEnd added in v1.2.0

func (buf *Buffer) SliceToEnd(start int) *Buffer

SliceToEnd is shorthand for Slice(start, buf.Len()) and returns the subpart from the position specified start to the last bit.

Example
ba := bitarray.MustParse("0011-1010 0110-1")
buf := bitarray.NewBufferFromBitArray(ba)

fmt.Println(buf.SliceToEnd(4))
fmt.Println(buf.SliceToEnd(9))
Output:

101001101
1101

func (Buffer) String

func (buf Buffer) String() string

String returns the string representation of the current content.

func (*Buffer) ToggleBitAt

func (buf *Buffer) ToggleBitAt(off int)

ToggleBitAt flips a single bit at the position specified by off in the buffer.

Example
ba := bitarray.MustParse("110010")
buf := bitarray.NewBufferFromBitArray(ba)

fmt.Println(buf)
buf.ToggleBitAt(1)
buf.ToggleBitAt(3)
buf.ToggleBitAt(5)
fmt.Println(buf)
Output:

110010
100111

func (*Buffer) ToggleBitsAt

func (buf *Buffer) ToggleBitsAt(off, nBits int)

ToggleBitsAt inverts the nBits bits starting at off.

Example
ba := bitarray.MustParse("11110000")
buf := bitarray.NewBufferFromBitArray(ba)

fmt.Println(buf)
buf.ToggleBitsAt(2, 4)
fmt.Println(buf)
Output:

11110000
11001100

func (*Buffer) TrailingZeros

func (buf *Buffer) TrailingZeros() int

TrailingZeros returns the number of trailing zero bits in the Buffer.

Example
ba := bitarray.MustParse("11110000")
buf := bitarray.NewBufferFromBitArray(ba)

fmt.Printf("%b: %d\n", buf, buf.TrailingZeros())
buf.ToggleBitsAt(6, 2)
fmt.Printf("%b: %d\n", buf, buf.TrailingZeros())
Output:

11110000: 4
11110011: 0

func (*Buffer) Uint16 added in v1.3.0

func (buf *Buffer) Uint16() uint16

Uint16 returns up to 16 bits from the beginning of the buffer as a uint16 value. If buf.Len() is greater than 16, only the first 16 bits are used. If buf.Len() is less than 16, it is treated as an integer with that number of bits. For example, if buf.Len() == 5, it returns a 5-bit integer, 0 to 31(=0b11111), as a uint16 value.

Example
b := []byte{0x12, 0x34, 0x56}
buf := bitarray.NewBufferFromByteSlice(b)

fmt.Printf("%04x\n", buf.Slice(4, 20).Uint16())
fmt.Printf("%04x\n", buf.Slice(8, 20).Uint16())
Output:

2345
0345

func (*Buffer) Uint32 added in v1.3.0

func (buf *Buffer) Uint32() uint32

Uint32 returns up to 32 bits from the beginning of the buffer as a uint32 value. If buf.Len() is greater than 32, only the first 32 bits are used. If buf.Len() is less than 32, it is treated as an integer with that number of bits. For example, if buf.Len() == 5, it returns a 5-bit integer, 0 to 31(=0b11111), as a uint32 value.

Example
b := []byte{0x12, 0x34, 0x56, 0x78, 0x9a}
buf := bitarray.NewBufferFromByteSlice(b)

fmt.Printf("%08x\n", buf.Slice(4, 36).Uint32())
fmt.Printf("%08x\n", buf.Slice(8, 20).Uint32())
Output:

23456789
00000345

func (*Buffer) Uint64 added in v1.3.0

func (buf *Buffer) Uint64() uint64

Uint64 returns up to 64 bits from the beginning of the buffer as a uint64 value. If buf.Len() is greater than 64, only the first 64 bits are used. If buf.Len() is less than 64, it is treated as an integer with that number of bits. For example, if buf.Len() == 5, it returns a 5-bit integer, 0 to 31(=0b11111), as a uint64 value.

Example
b := []byte{0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12}
buf := bitarray.NewBufferFromByteSlice(b)

fmt.Printf("%016x\n", buf.Slice(4, 68).Uint64())
fmt.Printf("%016x\n", buf.Slice(12, 24).Uint64())
Output:

23456789abcdef01
0000000000000456

func (*Buffer) Uint8 added in v1.3.0

func (buf *Buffer) Uint8() uint8

Uint8 returns up to 8 bits from the beginning of the buffer as a uint8 value. If buf.Len() is greater than 8, only the first 8 bits are used. If buf.Len() is less than 8, it is treated as an integer with that number of bits. For example, if buf.Len() == 5, it returns a 5-bit integer, 0 to 31(=0b11111), as a uint8 value.

Example
b := []byte{0b_1100_1010, 0b_1111_0000}
buf := bitarray.NewBufferFromByteSlice(b)

fmt.Println(buf.Slice(4, 12).Uint8()) // 1010 1111
fmt.Println(buf.Slice(8, 12).Uint8()) // 1111
fmt.Println(buf.Slice(4, 10).Uint8()) // 1010 11
Output:

175
15
43

func (*Buffer) XorAt

func (buf *Buffer) XorAt(off int, x BitArrayer)

XorAt applies a bitwise XOR operation with x at the offset off. XOR is applied only to the range from off to off+x.Len(), and other bits are preserved.

Example
ba := bitarray.MustParse("11110000")
buf := bitarray.NewBufferFromBitArray(ba)

fmt.Println(buf)
buf.XorAt(2, bitarray.MustParse("0110"))
fmt.Println(buf)
Output:

11110000
11101000

type Builder

type Builder struct {
	// contains filtered or unexported fields
}

Builder is used to efficiently build a BitArray using Write methods. It minimizes memory copying and bit shifting.

The zero value for Builder is already to use. Do not copy a non-zero Builder. It is not safe for concurrent use by multiple goroutines.

Example
b := bitarray.NewBuilder()

// Add bits with various methods.
b.WriteBitsFromBytes([]byte{0b_1100_0111}, 2, 3) // 000
b.WriteByte(0xFF)                                // 11111111
b.WriteBit(0)                                    // 0
b.WriteBitArray(bitarray.MustParse("111000111")) // 111000111
b.WriteByteBits([]byte{0, 1, 0, 1})              // 0101

// Build a BitArray containing the accumulated bits.
ba := b.BitArray()
fmt.Printf("% b\n", ba)
Output:

00011111 11101110 00111010 1

func NewBuilder

func NewBuilder(bas ...BitArrayer) *Builder

NewBuilder creates a Builder with bit arrays as the initial contents.

Example
// Create an empty builder and add bitarrays.
b1 := bitarray.NewBuilder()
b1.WriteBitArray(bitarray.MustParse("1111"))
b1.WriteBitArray(bitarray.MustParse("000"))
fmt.Printf("%b\n", b1.BitArray())

// Same as above.
b2 := bitarray.NewBuilder(
	bitarray.MustParse("1111"),
	bitarray.MustParse("000"),
)
fmt.Printf("%b\n", b2.BitArray())
Output:

1111000
1111000

func (*Builder) BitArray

func (b *Builder) BitArray() *BitArray

BitArray builds an immutable BitArray from accumulated bits. References to the accumulated byte slices are copied when this BitArray method is called.

Example
b := bitarray.NewBuilder()

b.WriteBitArray(bitarray.MustParse("1111-00"))
b.WriteBitArray(bitarray.MustParse("1100-11"))

ba := b.BitArray()
fmt.Printf("% b\n", ba)
Output:

11110011 0011

func (*Builder) Len

func (b *Builder) Len() int

Len returns the current number of bits accumurated.

Example
b := bitarray.NewBuilder()
b.WriteBitArray(bitarray.MustParse("1111-00"))
b.WriteBitArray(bitarray.MustParse("1100-11"))

fmt.Println(b.Len())
Output:

12

func (*Builder) ReadFrom

func (b *Builder) ReadFrom(r io.Reader) (int64, error)

ReadFrom implements io.ReaderFrom. It reads bytes from r until io.EOF or an error, and appends the bits read to the builder. Even if an error occurs, the bits that could be read before the error are appended to the builder.

Example
b := bitarray.NewBuilder(bitarray.MustParse("0000"))

src := bytes.NewReader([]byte{0xFF, 0x00, 0xAA})
n, err := b.ReadFrom(src)
if err != nil {
	panic(err)
}
fmt.Println(n)

ba := b.BitArray()
fmt.Printf("% b\n", ba)
Output:

3
00001111 11110000 00001010 1010

func (*Builder) Reset

func (b *Builder) Reset()

Reset resets the builder state to empty. All the bits accumulated by writing methods are discarded.

Example
b := bitarray.NewBuilder()

b.WriteBitArray(bitarray.MustParse("1111-00"))
b.WriteBitArray(bitarray.MustParse("1100-11"))

b.Reset()

b.WriteBitArray(bitarray.MustParse("111"))

fmt.Println(b)
Output:

111

func (*Builder) String

func (b *Builder) String() string

String returns the string representation of the bit array being built. The result is the same as b.BitArray().String().

Example
b := bitarray.NewBuilder()

b.WriteBitArray(bitarray.MustParse("1111-00"))
b.WriteBitArray(bitarray.MustParse("1100-11"))

fmt.Println(b.String())
fmt.Println(b.BitArray().String())
Output:

111100110011
111100110011

func (*Builder) Write

func (b *Builder) Write(p []byte) (int, error)

Write implements io.Writer by writing 8 * len(p) bits read from a byte slice p. Write copies p once because the io.Writer prohibits the implementation to retain p. Use WriteBitsFromBytes to avoid copying. Write always returns len(p), nil.

Example
b := bitarray.NewBuilder()

src := []byte{0xF0, 0xF0} // 1111-0000 1111-0000
n, err := b.Write(src)
if err != nil {
	panic(err)
}

fmt.Println(n)
fmt.Println(b)
Output:

2
1111000011110000
Example (Copy)
b := bitarray.NewBuilder(bitarray.MustParse("0000"))

src := bytes.NewReader([]byte{0xFF, 0x00, 0xAA})
_, err := io.Copy(b, src) // uses b.Write() via src.WriteTo()
if err != nil {
	panic(err)
}

ba := b.BitArray()
fmt.Printf("% b\n", ba)
Output:

00001111 11110000 00001010 1010

func (*Builder) WriteBit

func (b *Builder) WriteBit(bit byte) error

WriteBit writes a single bit to the builder. The bit should be 0 or 1, otherwise its LSB is silently used. It always returns a nil error.

Example
b := bitarray.NewBuilder()

b.WriteBit(0)
b.WriteBit(1)
b.WriteBit(0)
b.WriteBit(1)

fmt.Println(b)
Output:

0101

func (*Builder) WriteBitArray

func (b *Builder) WriteBitArray(x BitArrayer) (int, error)

WriteBitArray writes a bit array to the builder. It always returns the length of the bit array and a nil error.

Example
b := bitarray.NewBuilder()

b.WriteBitArray(bitarray.MustParse("111"))
b.WriteBitArray(bitarray.MustParse("0000"))

fmt.Println(b)
Output:

1110000

func (*Builder) WriteBits added in v1.3.0

func (b *Builder) WriteBits(p *Buffer) (int, error)

WriteBits write the bits read from a Buffer p. WriteBits copies p and is unaffected by changes to p after the call. It always returns p.Len() and nil error.

func (*Builder) WriteBitsFromBytes

func (b *Builder) WriteBitsFromBytes(p []byte, off, nBits int)

WriteBitsFromBytes adds the number of bits specified by nBits from the byte slice p to the Builder. It skips the off bits from the beginning of p and reads up to 8 bits from each byte from the MSB to the LSB.

WriteBitsFromBytes only references the slice and offset of p, and does not copy the contents of p. Therefore, any changes to the contents of p before calling the BitArray() or String() methods are affected. Be especially careful when using a same buffer for iterations.

Example
b := bitarray.NewBuilder()

src := []byte{0xF3, 0x50} // 1111-0011 0101-0000

b.WriteBitsFromBytes(src, 3, 4)  // 1001
b.WriteBitsFromBytes(src, 8, 0)  // (empty)
b.WriteBitsFromBytes(src, 5, 6)  // 011010
b.WriteBitsFromBytes(src, 11, 3) // 100

fmt.Println(b)
Output:

1001011010100

func (*Builder) WriteByte

func (b *Builder) WriteByte(c byte) error

WriteByte implements io.ByteWriter by writing 8 bits read from a byte c. WriteByte always returns a nil error.

func (*Builder) WriteByteBits

func (b *Builder) WriteByteBits(bits []byte)

WriteByteBits adds to the Builder the bits read from a byte slice where each element contains individual bits. Each element of bits should be 0 or 1, otherwise only its LSB is used silently. WriteByteBits copies the bits from bits, so any future changes to bits will not affect the contents of Builder.

Example
b := bitarray.NewBuilder()

src := []byte{1, 0, 1, 0, 1, 0}
b.WriteByteBits(src)

fmt.Println(b)
Output:

101010

type IterateFunc

type IterateFunc func(i, b int) error

IterateFunc is the type of the function called by Iterate to process each bit of a BitArray. The i argument contains the offset from the beginning. The b argument is the actual bit value, 0 or 1.

If the function returns the special error BreakIteration, Iterate breaks the current iteration without error. Otherwise, if the function returns a non-nil error, Iterate stops the current iteration and returns that error.

type Reader

type Reader struct {
	// contains filtered or unexported fields
}

Reader implements io.Reader and io.ByteReader interfaces by reading from a BitArray.

The standard io.Reader family interfaces define byte-oriented reading methods, rather than bit-oriented. And they always read in bytes and cannot read fractional bits less than 8 bits. When the number of remaining available bits is not a multiple of 8, the io.EOF may be reached with fractional bits remaining. In this case, the padding bits are not added automatically and an ErrFractionalBitsBeforeEOF is returned. To handle these trailing fractional bits, use bit-oriented reads together, or use ToPadded8 etc in advance to make sure that the number of bits in the source is a multiple of 8 bits.

func NewReader

func NewReader(ba BitArrayer) *Reader

NewReader returns a new Reader reading from the bit array ba. For mutable types of ba, the value at the time NewReader is called is copied and subsequent changes will not be reflected in future readings.

func (*Reader) Read

func (r *Reader) Read(p []byte) (int, error)

Read implements the io.Reader interface. It reads up to 8 * len(p) bits from the underlying BitArray, writes them to p as bytes, and returns the number of bytes read. It always reads in bytes, and if only fractional bits less than 8 bits are available, it returns an ErrFractionalBitsBeforeEOF.

func (*Reader) ReadBit

func (r *Reader) ReadBit() (byte, error)

ReadBit reads a single bit as 0 or 1.

func (*Reader) ReadBitArray

func (r *Reader) ReadBitArray(nBits int) (*BitArray, error)

ReadBitArray reads up to nBits bits as a BitArray. The returned BitArray may be shorter than nBits. The caller should check the length of the returned bit array and handle it.

func (*Reader) ReadBits

func (r *Reader) ReadBits(p *Buffer) (int, error)

ReadBits reads up to p.Len() bits into p. It returns the number of bits read (0 <= n <= p.Len()) and any error encountered. The data in the buffer beyond the returned length is undefined.

func (*Reader) ReadByte

func (r *Reader) ReadByte() (byte, error)

ReadByte implements the io.ByteReader interface. It reads 8 bits from the underlying BitArray and returns them as a byte. If only fractional bits less than 8 bits are available, it returns an ErrFractionalBitsBeforeEOF.

func (*Reader) Reset

func (r *Reader) Reset(ba BitArrayer)

Reset resets the Reader to be reading from ba.

type Slice

type Slice []*BitArray

Slice attaches the methods of sort.Interface to []*BitArray, sorting in increasing order.

func (Slice) Len

func (s Slice) Len() int

func (Slice) Less

func (s Slice) Less(i, j int) bool

func (Slice) Search

func (s Slice) Search(x BitArrayer) int

Search searches for x in the sorted slice s using binary search and returns the index. The return value is the index to insert x if x is not present (it could be s.Len()). The slice must be sorted in ascending order.

Example
bas := bitarray.Slice{
	bitarray.MustParse("1111-1111 0000"),
	bitarray.MustParse("1111-1111 0"),
	bitarray.MustParse("0000-0000 0000"),
	bitarray.MustParse("0"),
	bitarray.MustParse("0101-00"),
}

bas.Sort()

x := bitarray.MustParse("0o776")
idx := bas.Search(x)
fmt.Printf("%d: %b (%o)\n", idx, bas[idx], bas[idx])
Output:

3: 111111110 (776)

func (Slice) Sort

func (s Slice) Sort()

Sort is a convenience method: s.Sort() calls sort.Sort(s).

Example
bas := bitarray.Slice{
	bitarray.MustParse("1111-1111 0000"),
	bitarray.MustParse("1111-1111 0"),
	bitarray.MustParse("0000-0000 0000"),
	bitarray.MustParse("0"),
	bitarray.MustParse("0101-00"),
}

bas.Sort()
for i, ba := range bas {
	fmt.Printf("%d: % b\n", i, ba)
}
Output:

0: 0
1: 00000000 0000
2: 010100
3: 11111111 0
4: 11111111 0000

func (Slice) Swap

func (s Slice) Swap(i, j int)

Jump to

Keyboard shortcuts

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