user4611478
user4611478

Reputation: 371

How to shift byte array with Golang?

Here simple working code to left shift first bit of a byte

package main

import (
    "fmt"
)

type Byte byte

func SL(b Byte) Byte {
    if b&0x80 == 0x80 {
        b <<= 1
        b ^= 0x01
    } else {
        b <<= 1
    }
    return b
}

func main() {
    var b Byte
    b = 0xD3
    fmt.Printf("old byte %#08b\n", b) // 11010011
    c := SL(b)
    fmt.Printf("new byte %#08b", c)   // 10100111
}

What should I do to shift array of bytes, like type Byte [2]byte?

Thanks for advance!

Upvotes: 5

Views: 8524

Answers (5)

Ilia Choly
Ilia Choly

Reputation: 18557

Here's an implementation that can do both left and right shifts:

// ShiftLeft performs a left bit shift operation on the provided bytes.
// If the bits count is negative, a right bit shift is performed.
func ShiftLeft(data []byte, bits int) {
    n := len(data)
    if bits < 0 {
        bits = -bits
        for i := n - 1; i > 0; i-- {
            data[i] = data[i]>>bits | data[i-1]<<(8-bits)
        }
        data[0] >>= bits
    } else {
        for i := 0; i < n-1; i++ {
            data[i] = data[i]<<bits | data[i+1]>>(8-bits)
        }
        data[n-1] <<= bits
    }
}

Upvotes: 3

Coconut
Coconut

Reputation: 2222

shift left by multiple bits, expanding qin's answer:

func shiftBytesLeft(a []byte, byBits int) (dst []byte) {
    n := len(a)
    dst = make([]byte, n)
    for i := 0; i < n-1; i++ {
        dst[i] = a[i] << byBits
        dst[i] = (dst[i] & (0xff - byte(byBits))) | (a[i+1] >> (8 - byte(byBits)))
    }
    dst[n-1] = a[n-1] << byBits
    return dst
}

Upvotes: 2

qin
qin

Reputation: 1713

A solution to shift left 1 bit.

func shiftBytesLeft(a []byte) (dst []byte) {
    n := len(a)
    dst = make([]byte, n)
    for i := 0; i < n-1; i++ {
        dst[i] = a[i] << 1
        dst[i] = (dst[i] & 0xfe) | (a[i+1] >> 7)
    }
    dst[n-1] = a[n-1] << 1
    return dst
}

Upvotes: 4

Dave C
Dave C

Reputation: 7888

You appear to want to rotate, not shift. Any particular reason you aren't using a uint16 type instead of [2]byte?

Anyway, if you really want [2]byte, this is simpler and doesn't branch:

func rol(v [2]byte) [2]byte {
    x := int(v[0])<<8 | int(v[1])
    x <<= 1
    v[0] = byte(x >> 8)
    v[1] = byte((x & 0xff) | x>>16)
    return v
}

If you want to do such operations on an arbitrary large number of bits you could use math/big.

Upvotes: 3

user4611478
user4611478

Reputation: 371

Yep! I found a solution.

package main

import (
    "fmt"
)

type Byte [2]byte

//shift left
func SL(b Byte) Byte {
    if b[0]&0x80 == 0x80 {
        b[0] <<= 1
        if b[1]&0x80 == 0x80 {
            b[0] ^= 1
            b[1] <<= 1
        } else {
            b[1] <<= 1
        }
        b[1] ^= 0x01
    } else {
        b[0] <<= 1
        if b[1]&0x80 == 0x80 {
            b[0] ^= 1
            b[1] <<= 1
        } else {
            b[1] <<= 1
        }
    }
    return b
}

func main() {
    //var b Byte
    b := Byte{0x23, 0x86}
    fmt.Printf("old byte %#08b %#08b\n", b[0], b[1]) // 00100011 10000110
    c := SL(b)
    fmt.Printf("new byte %#08b %#08b", c[0], c[1]) // 01000111 00001100
}

Upvotes: 1

Related Questions