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) { ...@@ -181,6 +181,12 @@ func (d Decoder) Decode() (interface{}, error) {
err = d.binGet() err = d.binGet()
case opInst: case opInst:
err = d.inst() err = d.inst()
case opLong1:
err = d.loadLong1()
case opNewfalse:
err = d.loadBool(false)
case opNewtrue:
err = d.loadBool(true)
case opLongBinget: case opLongBinget:
err = d.longBinGet() err = d.longBinGet()
case opList: case opList:
...@@ -249,9 +255,11 @@ func (d *Decoder) push(v interface{}) { ...@@ -249,9 +255,11 @@ func (d *Decoder) push(v interface{}) {
// Pop a value // Pop a value
func (d *Decoder) pop() interface{} { func (d *Decoder) pop() interface{} {
fmt.Printf("stack before = %#v\n", d.stack)
ln := len(d.stack) - 1 ln := len(d.stack) - 1
v := d.stack[ln] v := d.stack[ln]
d.stack = d.stack[:ln] d.stack = d.stack[:ln]
fmt.Printf("stack after = %#v\n", d.stack)
return v return v
} }
...@@ -332,6 +340,29 @@ func (d *Decoder) loadLong() error { ...@@ -332,6 +340,29 @@ func (d *Decoder) loadLong() error {
return nil 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 // Push a 2-byte unsigned int
func (d *Decoder) loadBinInt2() error { func (d *Decoder) loadBinInt2() error {
var u uint16 var u uint16
...@@ -449,7 +480,24 @@ func (d *Decoder) loadUnicode() error { ...@@ -449,7 +480,24 @@ func (d *Decoder) loadUnicode() error {
} }
func (d *Decoder) loadBinUnicode() 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 { func (d *Decoder) loadAppend() error {
...@@ -532,6 +580,11 @@ func (d *Decoder) longBinGet() error { ...@@ -532,6 +580,11 @@ func (d *Decoder) longBinGet() error {
return nil return nil
} }
func (d *Decoder) loadBool(b bool) error {
d.push(b)
return nil
}
func (d *Decoder) loadList() error { func (d *Decoder) loadList() error {
k := d.marker() k := d.marker()
v := append([]interface{}{}, d.stack[k+1:]...) v := append([]interface{}{}, d.stack[k+1:]...)
...@@ -604,3 +657,47 @@ func (d *Decoder) binFloat() error { ...@@ -604,3 +657,47 @@ func (d *Decoder) binFloat() error {
d.stack = append(d.stack, math.Float64frombits(u)) d.stack = append(d.stack, math.Float64frombits(u))
return nil 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) { ...@@ -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