Skip to content
This repository has been archived by the owner on Jul 12, 2022. It is now read-only.

Commit

Permalink
[#4] Added byte array AND,OR,XOR,NOT operations (#30)
Browse files Browse the repository at this point in the history
Closes #4
  • Loading branch information
ulziibuyan authored and rlespinasse committed Oct 26, 2017
1 parent 8c1474d commit 6afb2e7
Show file tree
Hide file tree
Showing 2 changed files with 224 additions and 0 deletions.
69 changes: 69 additions & 0 deletions bytearray_operations.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,75 @@ func LeftShift(data []byte, shift uint64) []byte {
return result
}

// Mask apply AND mask to byte array
func Mask(data, mask []byte) []byte {
var dataLength = len(data)
if dataLength < 1 {
return data
}
result := make([]byte, dataLength)
copy(result, data)

var maskLength = len(mask)
var operationLength = maskLength
// If mask is longer than data, keep operation to (shorter) data length
if maskLength > dataLength {
operationLength = dataLength
}
for i := 1; i < operationLength+1; i++ {
result[dataLength-i] &= mask[maskLength-i]
}
return result
}

// InclusiveMerge two byte arrays
func InclusiveMerge(data1, data2 []byte) []byte {
var shorterData = data1
var longerData = data2
var longerLength = len(data2)
if longerLength < len(data1) {
shorterData = data2
longerData = data1
longerLength = len(data1)
}
result := make([]byte, longerLength)
copy(result[longerLength-len(shorterData):], shorterData)

for i := longerLength - 1; i > -1; i-- {
result[i] |= longerData[i]
}
return result
}

// ExclusiveMerge two byte arrays
func ExclusiveMerge(data1, data2 []byte) []byte {
var shorterData = data1
var longerData = data2
var longerLength = len(data2)
if longerLength < len(data1) {
shorterData = data2
longerData = data1
longerLength = len(data1)
}
result := make([]byte, longerLength)
copy(result[longerLength-len(shorterData):], shorterData)

for i := longerLength - 1; i > -1; i-- {
result[i] ^= longerData[i]
}
return result
}

// Not apply NOT operation to byte array
func Not(data []byte) []byte {
var dataLength = len(data)
result := make([]byte, dataLength)
for i := 0; i < dataLength; i++ {
result[i] = ^data[i]
}
return result
}

// ExtractBytes get a byte array as subset of another byte array
func ExtractBytes(data []byte, lsbPosition, msbPosition uint64) []byte {
var maxMsb = uint64(byteLength*len(data) - 1)
Expand Down
155 changes: 155 additions & 0 deletions bytearray_operations_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,161 @@ func TestLeftShift(t *testing.T) {
}
}

var testcasesMask = []struct {
name string
data []byte
mask []byte
result []byte
}{
{"data and mask of equal length", []byte{0xDA, 0x99, 0xBA}, []byte{0xAD, 0x11, 0xAB}, []byte{0x88, 0x11, 0xAA}},
{"data shorter than mask", []byte{0xDA, 0x99, 0xBA}, []byte{0xAD, 0x11, 0xAB, 0x88, 0x11, 0xAA}, []byte{0x88, 0x11, 0xAA}},
{"data longer than mask", []byte{0xAD, 0x11, 0xAB, 0x88, 0x11, 0xAA}, []byte{0xDA, 0x99, 0xBA}, []byte{0xAD, 0x11, 0xAB, 0x88, 0x11, 0xAA}},
{"empty mask on data", []byte{0xDA, 0x99, 0xBA}, []byte{}, []byte{0xDA, 0x99, 0xBA}},
{"mask on empty data", []byte{}, []byte{0xAD, 0x11, 0xAB}, []byte{}},
{"empty mask on empty data", []byte{}, []byte{}, []byte{}},
}

func TestMask(t *testing.T) {
var val []byte
for _, tc := range testcasesMask {
t.Run(tc.name, func(t *testing.T) {
val = Mask(tc.data, tc.mask)
if !reflect.DeepEqual(val, tc.result) {
t.Errorf("Mask(%x, %x) was %x, should be %x",
tc.data, tc.mask,
val,
tc.result)
}
})
}
}

func BenchmarkMask(b *testing.B) {
var val []byte
for _, tc := range testcasesMask {
b.Run(tc.name, func(b *testing.B) {
for i := 0; i < b.N; i++ {
val = Mask(tc.data, tc.mask)
}
})
}
}

var testcasesInclusiveMerge = []struct {
name string
data1 []byte
data2 []byte
result []byte
}{
{"equal length arrays", []byte{0xDA, 0x99, 0xBA}, []byte{0xAD, 0x11, 0xAB}, []byte{0xFF, 0x99, 0xBB}},
{"first array longer", []byte{0xAD, 0x11, 0xAB, 0xFF, 0x99, 0xBB}, []byte{0xDA, 0x99, 0xBA}, []byte{0xAD, 0x11, 0xAB, 0xFF, 0x99, 0xBB}},
{"second array longer", []byte{0xDA, 0x99, 0xBA}, []byte{0xAD, 0x11, 0xAB, 0xFF, 0x99, 0xBB}, []byte{0xAD, 0x11, 0xAB, 0xFF, 0x99, 0xBB}},
{"first array empty", []byte{}, []byte{0xAD, 0x11, 0xAB}, []byte{0xAD, 0x11, 0xAB}},
{"second array empty", []byte{0xDA, 0x99, 0xBA}, []byte{}, []byte{0xDA, 0x99, 0xBA}},
{"empty arrays", []byte{}, []byte{}, []byte{}},
}

func TestInclusiveMerge(t *testing.T) {
var val []byte
for _, tc := range testcasesInclusiveMerge {
t.Run(tc.name, func(t *testing.T) {
val = InclusiveMerge(tc.data1, tc.data2)
if !reflect.DeepEqual(val, tc.result) {
t.Errorf("InclusiveMerge(%x, %x) was %x, should be %x",
tc.data1, tc.data2,
val,
tc.result)
}
})
}
}

func BenchmarkInclusiveMerge(b *testing.B) {
var val []byte
for _, tc := range testcasesInclusiveMerge {
b.Run(tc.name, func(b *testing.B) {
for i := 0; i < b.N; i++ {
val = InclusiveMerge(tc.data1, tc.data2)
}
})
}
}

var testcasesExclusiveMerge = []struct {
name string
data1 []byte
data2 []byte
result []byte
}{
{"equal length arrays", []byte{0xDA, 0x99, 0xBA}, []byte{0xAD, 0x11, 0xAB}, []byte{0x77, 0x88, 0x11}},
{"first array longer", []byte{0xAD, 0x11, 0xAB, 0x77, 0x88, 0x11}, []byte{0xDA, 0x99, 0xBA}, []byte{0xAD, 0x11, 0xAB, 0xAD, 0x11, 0xAB}},
{"second array longer", []byte{0xAD, 0x11, 0xAB}, []byte{0xAB, 0xCD, 0xEF, 0x77, 0x88, 0x11}, []byte{0xAB, 0xCD, 0xEF, 0xDA, 0x99, 0xBA}},
{"first array empty", []byte{}, []byte{0xAD, 0x11, 0xAB}, []byte{0xAD, 0x11, 0xAB}},
{"second array empty", []byte{0xDA, 0x99, 0xBA}, []byte{}, []byte{0xDA, 0x99, 0xBA}},
{"empty arrays", []byte{}, []byte{}, []byte{}},
}

func TestExclusiveMerge(t *testing.T) {
var val []byte
for _, tc := range testcasesExclusiveMerge {
t.Run(tc.name, func(t *testing.T) {
val = ExclusiveMerge(tc.data1, tc.data2)
if !reflect.DeepEqual(val, tc.result) {
t.Errorf("ExclusiveMerge(%x, %x) was %x, should be %x",
tc.data1, tc.data2,
val,
tc.result)
}
})
}
}

func BenchmarkExclusiveMerge(b *testing.B) {
var val []byte
for _, tc := range testcasesExclusiveMerge {
b.Run(tc.name, func(b *testing.B) {
for i := 0; i < b.N; i++ {
val = ExclusiveMerge(tc.data1, tc.data2)
}
})
}
}

var testcasesNot = []struct {
name string
data []byte
result []byte
}{
{"not empty array", []byte{0xDA, 0x99, 0xBA}, []byte{0x25, 0x66, 0x45}},
{"empty array", []byte{}, []byte{}},
}

func TestNot(t *testing.T) {
var val []byte
for _, tc := range testcasesNot {
t.Run(tc.name, func(t *testing.T) {
val = Not(tc.data)
if !reflect.DeepEqual(val, tc.result) {
t.Errorf("Not(%x) was %x, should be %x",
tc.data,
val,
tc.result)
}
})
}
}

func BenchmarkNot(b *testing.B) {
var val []byte
for _, tc := range testcasesNot {
b.Run(tc.name, func(b *testing.B) {
for i := 0; i < b.N; i++ {
val = Not(tc.data)
}
})
}
}

func BenchmarkLeftShift(b *testing.B) {
var val []byte
for _, tc := range testcasesLeftShift {
Expand Down

0 comments on commit 6afb2e7

Please sign in to comment.