Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package bits
- import (
- "fmt"
- "strings"
- )
- const (
- blen = 8
- Invalid = -1
- )
- type Bits struct {
- buf []byte
- }
- func New(buf []byte) (*Bits, error) {
- if len(buf) == 0 {
- return nil, fmt.Errorf("can not create a Bits from an empty buffer")
- }
- return &Bits{buf}, nil
- }
- func (b Bits) Len() int {
- return len(b.buf) * blen
- }
- func (b Bits) String() string {
- parts := make([]string, len(b.buf))
- for i, v := range b.buf {
- parts[i] = fmt.Sprintf("%0*b", blen, v)
- }
- return strings.Join(parts, "")
- }
- func (b *Bits) RotateLeft(c int) error {
- if c <= 0 {
- return fmt.Errorf("can not rotate with c <= 0")
- }
- return nil
- }
- func (b *Bits) RotateRight(c int) error {
- if c <= 0 {
- return fmt.Errorf("can not rotate with c <= 0")
- }
- return nil
- }
- func (b Bits) GetBit(pos int) (int64, error) {
- if pos < 0 || pos > b.Len() {
- return Invalid, fmt.Errorf("invalid position %d", pos)
- } else {
- ix, off := pos/blen, pos%blen
- val := int64(b.buf[ix]) & (128 >> uint(off))
- return val >> uint(blen-off-1), nil
- }
- }
- func (b Bits) GetBits(pos, length int, swap bool) (int64, error) {
- if pos < 0 || pos-length > b.Len() {
- return Invalid, fmt.Errorf("invalid position %d", pos)
- }
- switch length {
- case 0:
- return Invalid, fmt.Errorf("length must be greater than 0")
- case 1:
- return b.GetBit(pos)
- default:
- var sum int64
- s := pos / blen
- e := s + ((length + (length % blen)) / blen)
- d := length - blen
- buf := b.buf[s:e]
- if swap {
- mid, mod := len(buf)/2, len(buf)%2
- if mod%2 != 0 {
- return Invalid, fmt.Errorf("can not swap")
- }
- tmp := make([]byte, len(buf), len(buf))
- for _, b := range buf {
- tmp[mid] = b
- mid++
- if mid >= len(buf) {
- mid = 0
- }
- }
- buf = tmp
- }
- for i, v := range buf {
- m := int64((1 << uint(d)) - 1)
- d = length - d
- sum += (int64(v) & m) << uint(8*(len(buf)-i-1))
- }
- return sum, nil
- }
- }
- //Uint returns a big endian integer from Bits.
- func (b Bits) Uint(pos, length int) int64 {
- if v, err := b.GetBits(pos, length, false); err != nil {
- return Invalid
- } else {
- return v
- }
- }
- //UintLe returns an unsigned little endian integer from Bits.
- func (b Bits) UintLe(pos, length int) int64 {
- if v, err := b.GetBits(pos, length, true); err != nil {
- return Invalid
- } else {
- return v
- }
- }
- //Int returns a big endian Integer from Bits.
- func (b Bits) Int(pos, length int) int64 {
- if v, err := b.GetBits(pos, length, false); err != nil {
- return Invalid
- } else {
- if b.IsSet(pos) {
- v = (1<<uint(length) - 1) + ^v
- }
- return v
- }
- }
- //IntLe returns a little endian integer from Bits.
- func (b Bits) IntLe(pos, length int) int64 {
- if v, err := b.GetBits(pos, length, true); err != nil {
- return Invalid
- } else {
- if b.IsSet(pos) {
- v = (1<<uint(length) - 1) + ^v
- }
- return v
- }
- }
- func (b Bits) IsSet(pos int) bool {
- if v, err := b.GetBit(pos); err != nil {
- return false
- } else {
- return v == 1
- }
- }
- func (b Bits) AreSets(pos ...int) bool {
- for _, p := range pos {
- if !b.IsSet(p) {
- return false
- }
- }
- return true
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement