This repository has been archived by the owner on Jul 12, 2022. It is now read-only.
-
-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[#7] support little/big endian operations on a byte array
- Create BigEndianOperations accessor with - Mask function, - InclusiveMerge function, - ExclusiveMerge function, - ExtractBytes function. - Create LittleEndianOperations accessor with - Mask function, - InclusiveMerge function, - ExclusiveMerge function, - ExtractBytes function. - [#31] Fix LeftShift and RightShift functions. - Add some Endianess-free operations - Add Mask function on two arrays of the same size, - Add InclusiveMerge function on two arrays of the same size, - Add ExclusiveMerge function on two arrays of the same size, - Add LeftPad function, - Add RightPad function. Closes #7, #31
- Loading branch information
1 parent
92c23b7
commit c25839e
Showing
6 changed files
with
638 additions
and
218 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
package byteness | ||
|
||
type bigEndianOperations struct{} | ||
|
||
// BigEndianOperations test | ||
var BigEndianOperations = &bigEndianOperations{} | ||
|
||
// Mask apply AND mask to byte array | ||
func (op *bigEndianOperations) Mask(data, mask []byte) []byte { | ||
var dataLength = len(data) | ||
if dataLength < 1 { | ||
return data | ||
} | ||
|
||
var maskLength = len(mask) | ||
var operationLength = dataLength | ||
var operationCut = dataLength | ||
if maskLength > dataLength { | ||
operationLength = maskLength | ||
} | ||
|
||
result, _ := Mask(rightPad(data, operationLength, 0xFF), rightPad(mask, operationLength, 0xFF)) | ||
return result[:operationCut] | ||
} | ||
|
||
// InclusiveMerge apply OR operation on two byte arrays | ||
func (op *bigEndianOperations) InclusiveMerge(data1, data2 []byte) []byte { | ||
var data1Length = len(data1) | ||
var data2Length = len(data2) | ||
|
||
var operationLength = data1Length | ||
if data2Length > data1Length { | ||
operationLength = data2Length | ||
} | ||
|
||
result, _ := InclusiveMerge(rightPad(data1, operationLength, 0x00), rightPad(data2, operationLength, 0x00)) | ||
return result | ||
} | ||
|
||
// ExclusiveMerge apply XOR operation on two byte arrays | ||
func (op *bigEndianOperations) ExclusiveMerge(data1, data2 []byte) []byte { | ||
var data1Length = len(data1) | ||
var data2Length = len(data2) | ||
|
||
var operationLength = data1Length | ||
if data2Length > data1Length { | ||
operationLength = data2Length | ||
} | ||
|
||
result, _ := ExclusiveMerge(rightPad(data1, operationLength, 0x00), rightPad(data2, operationLength, 0x00)) | ||
return result | ||
} | ||
|
||
// ExtractBytes get a byte array as subset of another byte array | ||
func (op *bigEndianOperations) ExtractBytes(data []byte, lsbPosition, msbPosition uint64) []byte { | ||
var maxMsb = uint64(byteLength*len(data) - 1) | ||
|
||
if msbPosition <= lsbPosition || lsbPosition > maxMsb { | ||
return make([]byte, 0) | ||
} | ||
|
||
if msbPosition > maxMsb { | ||
msbPosition = maxMsb | ||
} | ||
|
||
var result = RightShift(data, maxMsb-msbPosition) | ||
var correctiveShift = maxMsb - msbPosition + lsbPosition | ||
result = LeftShift(result, correctiveShift) | ||
|
||
var size = computeSize(lsbPosition, msbPosition) | ||
return op.trim(result, size) | ||
} | ||
|
||
func (op *bigEndianOperations) trim(data []byte, newSize uint64) []byte { | ||
return data[:newSize] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,169 @@ | ||
package byteness | ||
|
||
import ( | ||
"reflect" | ||
"testing" | ||
) | ||
|
||
var testcasesBigEndianOperationsMask = []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{0x88, 0x11, 0xAA, 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 TestBigEndianOperationsMask(t *testing.T) { | ||
var val []byte | ||
for _, tc := range testcasesBigEndianOperationsMask { | ||
t.Run(tc.name, func(t *testing.T) { | ||
val = BigEndianOperations.Mask(tc.data, tc.mask) | ||
if !reflect.DeepEqual(val, tc.result) { | ||
t.Errorf("BigEndianOperations.Mask(%x, %x) was %x, should be %x", | ||
tc.data, tc.mask, | ||
val, | ||
tc.result) | ||
} | ||
}) | ||
} | ||
} | ||
|
||
func BenchmarkBigEndianOperationsMask(b *testing.B) { | ||
var val []byte | ||
for _, tc := range testcasesBigEndianOperationsMask { | ||
b.Run(tc.name, func(b *testing.B) { | ||
for i := 0; i < b.N; i++ { | ||
val = BigEndianOperations.Mask(tc.data, tc.mask) | ||
} | ||
}) | ||
} | ||
} | ||
|
||
var testcasesBigEndianOperationsInclusiveMerge = []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{0xFF, 0x99, 0xBB, 0xFF, 0x99, 0xBB}}, | ||
{"second array longer", []byte{0xDA, 0x99, 0xBA}, []byte{0xAD, 0x11, 0xAB, 0xFF, 0x99, 0xBB}, []byte{0xFF, 0x99, 0xBB, 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 TestBigEndianOperationsInclusiveMerge(t *testing.T) { | ||
var val []byte | ||
for _, tc := range testcasesBigEndianOperationsInclusiveMerge { | ||
t.Run(tc.name, func(t *testing.T) { | ||
val = BigEndianOperations.InclusiveMerge(tc.data1, tc.data2) | ||
if !reflect.DeepEqual(val, tc.result) { | ||
t.Errorf("BigEndianOperations.InclusiveMerge(%x, %x) was %x, should be %x", | ||
tc.data1, tc.data2, | ||
val, | ||
tc.result) | ||
} | ||
}) | ||
} | ||
} | ||
|
||
func BenchmarkBigEndianOperationsInclusiveMerge(b *testing.B) { | ||
var val []byte | ||
for _, tc := range testcasesBigEndianOperationsInclusiveMerge { | ||
b.Run(tc.name, func(b *testing.B) { | ||
for i := 0; i < b.N; i++ { | ||
val = BigEndianOperations.InclusiveMerge(tc.data1, tc.data2) | ||
} | ||
}) | ||
} | ||
} | ||
|
||
var testcasesBigEndianOperationsExclusiveMerge = []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{0x77, 0x88, 0x11, 0x77, 0x88, 0x11}}, | ||
{"second array longer", []byte{0xDA, 0x99, 0xBA}, []byte{0xAD, 0x11, 0xAB, 0x77, 0x88, 0x11}, []byte{0x77, 0x88, 0x11, 0x77, 0x88, 0x11}}, | ||
{"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 TestBigEndianOperationsExclusiveMerge(t *testing.T) { | ||
var val []byte | ||
for _, tc := range testcasesBigEndianOperationsExclusiveMerge { | ||
t.Run(tc.name, func(t *testing.T) { | ||
val = BigEndianOperations.ExclusiveMerge(tc.data1, tc.data2) | ||
if !reflect.DeepEqual(val, tc.result) { | ||
t.Errorf("BigEndianOperations.ExclusiveMerge(%x, %x) was %x, should be %x", | ||
tc.data1, tc.data2, | ||
val, | ||
tc.result) | ||
} | ||
}) | ||
} | ||
} | ||
|
||
func BenchmarkBigEndianOperationsExclusiveMerge(b *testing.B) { | ||
var val []byte | ||
for _, tc := range testcasesBigEndianOperationsExclusiveMerge { | ||
b.Run(tc.name, func(b *testing.B) { | ||
for i := 0; i < b.N; i++ { | ||
val = BigEndianOperations.ExclusiveMerge(tc.data1, tc.data2) | ||
} | ||
}) | ||
} | ||
} | ||
|
||
var testcasesBigEndianOperationsExtractBytes = []struct { | ||
name string | ||
data []byte | ||
lsbPosition, msbPosition uint64 | ||
result []byte | ||
}{ | ||
{"extract nothing", []byte{0xDA, 0x99, 0xBA}, 0, 0, []byte{}}, | ||
{"extract nothing due to inversed positions", []byte{0xDA, 0x99, 0xBA}, 16, 8, []byte{}}, | ||
{"extract nothing due to wrong positions", []byte{0xDA, 0x99, 0xBA}, 100, 101, []byte{}}, | ||
{"extract only in one byte", []byte{0xDA, 0x99, 0xBA}, 5, 7, []byte{0x40}}, | ||
{"extract one byte over two bytes", []byte{0xDA, 0x99, 0xBA}, 7, 8, []byte{0x40}}, | ||
{"extract two bytes over three bytes", []byte{0xDA, 0x99, 0xBA}, 6, 17, []byte{0xA6, 0x60}}, | ||
{"extract three bytes over three bytes", []byte{0xDA, 0x99, 0xBA}, 1, 22, []byte{0xB5, 0x33, 0x74}}, | ||
{"extract all bytes", []byte{0xDA, 0x99, 0xBA}, 0, 23, []byte{0xDA, 0x99, 0xBA}}, | ||
{"extract all bytes with an overflow position", []byte{0xDA, 0x99, 0xBA}, 0, 100, []byte{0xDA, 0x99, 0xBA}}, | ||
} | ||
|
||
func TestBigEndianOperationsExtractBytes(t *testing.T) { | ||
var val []byte | ||
for _, tc := range testcasesBigEndianOperationsExtractBytes { | ||
t.Run(tc.name, func(t *testing.T) { | ||
val = BigEndianOperations.ExtractBytes(tc.data, tc.lsbPosition, tc.msbPosition) | ||
if !reflect.DeepEqual(val, tc.result) { | ||
t.Errorf("BigEndianOperations.ExtractBytes(%x, %v, %v) was %x, should be %x", | ||
tc.data, tc.lsbPosition, tc.msbPosition, | ||
val, | ||
tc.result) | ||
} | ||
}) | ||
} | ||
} | ||
|
||
func BenchmarkBigEndianOperationsExtractBytes(b *testing.B) { | ||
var val []byte | ||
for _, tc := range testcasesBigEndianOperationsExtractBytes { | ||
b.Run(tc.name, func(b *testing.B) { | ||
for i := 0; i < b.N; i++ { | ||
val = BigEndianOperations.ExtractBytes(tc.data, tc.lsbPosition, tc.msbPosition) | ||
} | ||
}) | ||
} | ||
} |
Oops, something went wrong.