Commit bacb62b4 authored by Jonathan Pulfer's avatar Jonathan Pulfer

Implement binunicode and long1

parent 28ab321f
......@@ -181,6 +181,12 @@ func (d Decoder) Decode() (interface{}, error) {
err = d.binGet()
case opInst:
err = d.inst()
case opLong1:
err = d.loadLong1()
case opNewfalse:
err = d.loadBool(false)
case opNewtrue:
err = d.loadBool(true)
case opLongBinget:
err = d.longBinGet()
case opList:
......@@ -249,9 +255,11 @@ func (d *Decoder) push(v interface{}) {
// Pop a value
func (d *Decoder) pop() interface{} {
fmt.Printf("stack before = %#v\n", d.stack)
ln := len(d.stack) - 1
v := d.stack[ln]
d.stack = d.stack[:ln]
fmt.Printf("stack after = %#v\n", d.stack)
return v
}
......@@ -332,6 +340,29 @@ func (d *Decoder) loadLong() error {
return nil
}
// Push a long1
func (d *Decoder) loadLong1() error {
rawNum := []byte{}
b, err := d.r.ReadByte()
if err != nil {
return err
}
length, err := decodeLong(string(b))
if err != nil {
return err
}
for i := 0; int64(i) < length.Int64(); i++ {
b2, err := d.r.ReadByte()
if err != nil {
return err
}
rawNum = append(rawNum, b2)
}
decodedNum, err := decodeLong(string(rawNum))
d.push(decodedNum)
return nil
}
// Push a 2-byte unsigned int
func (d *Decoder) loadBinInt2() error {
var u uint16
......@@ -449,7 +480,24 @@ func (d *Decoder) loadUnicode() error {
}
func (d *Decoder) loadBinUnicode() error {
return errNotImplemented
var length int32
for i := 0; i < 4; i++ {
t, err := d.r.ReadByte()
if err != nil {
return err
}
length = length | (int32(t) << uint(8*i))
}
rawB := []byte{}
for z := 0; int32(z) < length; z++ {
n, err := d.r.ReadByte()
if err != nil {
return err
}
rawB = append(rawB, n)
}
d.push(string(rawB))
return nil
}
func (d *Decoder) loadAppend() error {
......@@ -532,6 +580,11 @@ func (d *Decoder) longBinGet() error {
return nil
}
func (d *Decoder) loadBool(b bool) error {
d.push(b)
return nil
}
func (d *Decoder) loadList() error {
k := d.marker()
v := append([]interface{}{}, d.stack[k+1:]...)
......@@ -604,3 +657,47 @@ func (d *Decoder) binFloat() error {
d.stack = append(d.stack, math.Float64frombits(u))
return nil
}
// decode_long takes a byte array of 2's compliment little-endian binary words and converts them
// to a big integer
func decodeLong(data string) (*big.Int, error) {
decoded := big.NewInt(0)
var negative bool
switch x := len(data); {
case x < 1:
return decoded, nil
case x > 1:
if data[x-1] > 127 {
negative = true
}
for i := x - 1; i >= 0; i-- {
a := big.NewInt(int64(data[i]))
for n := i; n > 0; n-- {
a = a.Lsh(a, 8)
}
decoded = decoded.Add(a, decoded)
}
default:
if data[0] > 127 {
negative = true
}
decoded = big.NewInt(int64(data[0]))
}
if negative {
// Subtract 1 from the number
one := big.NewInt(1)
decoded.Sub(decoded, one)
// Flip the bits
bytes := decoded.Bytes()
for i := 0; i < len(bytes); i++ {
bytes[i] = ^bytes[i]
}
decoded.SetBytes(bytes)
// Mark as negative now conversion has been completed
decoded.Neg(decoded)
}
return decoded, nil
}
......@@ -64,3 +64,102 @@ func TestDecode(t *testing.T) {
}
}
}
func TestZeroLengthData(t *testing.T) {
data := ""
output, err := decodeLong(data)
if err != nil {
t.Errorf("Error from decodeLong - %v\n", err)
}
if output.BitLen() > 0 {
t.Fail()
}
}
func TestValue1(t *testing.T) {
data := "\xff\x00"
output, err := decodeLong(data)
if err != nil {
t.Errorf("Error from decodeLong - %v\n", err)
}
target := big.NewInt(255)
if target.Cmp(output) != 0 {
t.Fail()
}
}
func TestValue2(t *testing.T) {
data := "\xff\x7f"
output, err := decodeLong(data)
if err != nil {
t.Errorf("Error from decodeLong - %v\n", err)
}
target := big.NewInt(32767)
if target.Cmp(output) != 0 {
t.Fail()
}
}
func TestValue3(t *testing.T) {
data := "\x00\xff"
output, err := decodeLong(data)
if err != nil {
t.Errorf("Error from decodeLong - %v\n", err)
}
target := big.NewInt(256)
target.Neg(target)
if target.Cmp(output) != 0 {
t.Logf("\nGot %v\nExpecting %v\n", output, target)
t.Fail()
}
}
func TestValue4(t *testing.T) {
data := "\x00\x80"
output, err := decodeLong(data)
if err != nil {
t.Errorf("Error from decodeLong - %v\n", err)
}
target := big.NewInt(32768)
target.Neg(target)
if target.Cmp(output) != 0 {
t.Logf("\nGot %v\nExpecting %v\n", output, target)
t.Fail()
}
}
func TestValue5(t *testing.T) {
data := "\x80"
output, err := decodeLong(data)
if err != nil {
t.Errorf("Error from decodeLong - %v\n", err)
}
target := big.NewInt(128)
target.Neg(target)
if target.Cmp(output) != 0 {
t.Logf("\nGot %v\nExpecting %v\n", output, target)
t.Fail()
}
}
func TestValue6(t *testing.T) {
data := "\x7f"
output, err := decodeLong(data)
if err != nil {
t.Errorf("Error from decodeLong - %v\n", err)
}
target := big.NewInt(127)
if target.Cmp(output) != 0 {
t.Fail()
}
}
func BenchmarkSpeed(b *testing.B) {
for i := 0; i < b.N; i++ {
data := "\x00\x80"
_, err := decodeLong(data)
if err != nil {
b.Errorf("Error from decodeLong - %v\n", err)
}
}
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment