summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRob Pike <r@golang.org>2009-06-29 15:15:07 -0700
committerRob Pike <r@golang.org>2009-06-29 15:15:07 -0700
commit24323437280c7f0a166b7f2fae75620470cde0f9 (patch)
treeec69f2b7fb0fcfe7288bf4cfad2c7cab756e95fc /src
parent1fd19170de0e30d771df54fff7557f870b2e3c14 (diff)
downloadgolang-24323437280c7f0a166b7f2fae75620470cde0f9.tar.gz
integer encode/decode
R=rsc DELTA=185 (175 added, 10 deleted, 0 changed) OCL=30863 CL=30871
Diffstat (limited to 'src')
-rw-r--r--src/pkg/gob/codec_test.go98
-rw-r--r--src/pkg/gob/decode.go40
-rw-r--r--src/pkg/gob/encode.go40
-rw-r--r--src/pkg/gob/type_test.go10
4 files changed, 178 insertions, 10 deletions
diff --git a/src/pkg/gob/codec_test.go b/src/pkg/gob/codec_test.go
new file mode 100644
index 000000000..8142aac69
--- /dev/null
+++ b/src/pkg/gob/codec_test.go
@@ -0,0 +1,98 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package gob
+
+import (
+ "bytes";
+ "gob";
+ "io";
+ "os";
+ "testing";
+)
+
+// Guarantee encoding format by comparing some encodings to hand-written values
+type EncodeT struct {
+ x uint64;
+ b []byte;
+}
+var encodeT = []EncodeT {
+ EncodeT{ 0x00, []byte{0x80} },
+ EncodeT{ 0x0f, []byte{0x8f} },
+ EncodeT{ 0xff, []byte{0x7f, 0x81} },
+ EncodeT{ 0xffff, []byte{0x7f, 0x7f, 0x83} },
+ EncodeT{ 0xffffff, []byte{0x7f, 0x7f, 0x7f, 0x87} },
+ EncodeT{ 0xffffffff, []byte{0x7f, 0x7f, 0x7f, 0x7f, 0x8f} },
+ EncodeT{ 0xffffffffff, []byte{0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x9f} },
+ EncodeT{ 0xffffffffffff, []byte{0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0xbf} },
+ EncodeT{ 0xffffffffffffff, []byte{0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0xff} },
+ EncodeT{ 0xffffffffffffffff, []byte{0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x81} },
+ EncodeT{ 0x1111, []byte{0x11, 0xa2} },
+ EncodeT{ 0x1111111111111111, []byte{0x11, 0x22, 0x44, 0x08, 0x11, 0x22, 0x44, 0x08, 0x91} },
+ EncodeT{ 0x8888888888888888, []byte{0x08, 0x11, 0x22, 0x44, 0x08, 0x11, 0x22, 0x44, 0x08, 0x81} },
+ EncodeT{ 1<<63, []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81} },
+}
+
+// Test basic encode/decode routines for unsigned integers
+func TestUintCodec(t *testing.T) {
+ var b = new(io.ByteBuffer);
+ for i, tt := range encodeT {
+ b.Reset();
+ err := EncodeUint(b, tt.x);
+ if err != nil {
+ t.Error("EncodeUint:", tt.x, err)
+ }
+ if !bytes.Equal(tt.b, b.Data()) {
+ t.Errorf("EncodeUint: expected % x got % x", tt.b, b.Data())
+ }
+ }
+ for u := uint64(0); ; u = (u+1) * 7 {
+ b.Reset();
+ err := EncodeUint(b, u);
+ if err != nil {
+ t.Error("EncodeUint:", u, err)
+ }
+ v, err := DecodeUint(b);
+ if err != nil {
+ t.Error("DecodeUint:", u, err)
+ }
+ if u != v {
+ t.Errorf("Encode/Decode: sent %#x received %#x\n", u, v)
+ }
+ if u & (1<<63) != 0 {
+ break
+ }
+ }
+}
+
+func verifyInt(i int64, t *testing.T) {
+ var b = new(io.ByteBuffer);
+ err := EncodeInt(b, i);
+ if err != nil {
+ t.Error("EncodeInt:", i, err)
+ }
+ j, err := DecodeInt(b);
+ if err != nil {
+ t.Error("DecodeInt:", i, err)
+ }
+ if i != j {
+ t.Errorf("Encode/Decode: sent %#x received %#x\n", uint64(i), uint64(j))
+ }
+}
+
+// Test basic encode/decode routines for signed integers
+func TestIntCodec(t *testing.T) {
+ var b = new(io.ByteBuffer);
+ for u := uint64(0); ; u = (u+1) * 7 {
+ // Do positive and negative values
+ i := int64(u);
+ verifyInt(i, t);
+ verifyInt(-i, t);
+ verifyInt(^i, t);
+ if u & (1<<63) != 0 {
+ break
+ }
+ }
+ verifyInt(-1<<63, t); // a tricky case
+}
diff --git a/src/pkg/gob/decode.go b/src/pkg/gob/decode.go
new file mode 100644
index 000000000..5104627cd
--- /dev/null
+++ b/src/pkg/gob/decode.go
@@ -0,0 +1,40 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package gob
+
+import (
+ "io";
+ "os";
+)
+
+// DecodeUint reads an encoded unsigned integer from r.
+func DecodeUint(r io.Reader) (x uint64, err os.Error) {
+ var buf [1]byte;
+ for shift := uint(0);; shift += 7 {
+ n, err := r.Read(&buf);
+ if n != 1 {
+ return 0, err
+ }
+ b := uint64(buf[0]);
+ x |= b << shift;
+ if b&0x80 != 0 {
+ x &^= 0x80 << shift;
+ break
+ }
+ }
+ return x, nil;
+}
+
+// DecodeInt reads an encoded signed integer from r.
+func DecodeInt(r io.Reader) (i int64, err os.Error) {
+ x, err := DecodeUint(r);
+ if err != nil {
+ return
+ }
+ if x & 1 != 0 {
+ return ^int64(x>>1), nil
+ }
+ return int64(x >> 1), nil
+}
diff --git a/src/pkg/gob/encode.go b/src/pkg/gob/encode.go
new file mode 100644
index 000000000..ecddee23e
--- /dev/null
+++ b/src/pkg/gob/encode.go
@@ -0,0 +1,40 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package gob
+
+import (
+ "io";
+ "os";
+)
+
+// Integers encode as a variant of Google's protocol buffer varint (varvarint?).
+// The variant is that the continuation bytes have a zero top bit instead of a one.
+// That way there's only one bit to clear and the value is a little easier to see if
+// you're the unfortunate sort of person who must read the hex to debug.
+
+// EncodeUint writes an encoded unsigned integer to w.
+func EncodeUint(w io.Writer, x uint64) os.Error {
+ var buf [16]byte;
+ var n int;
+ for n = 0; x > 127; n++ {
+ buf[n] = uint8(x & 0x7F);
+ x >>= 7;
+ }
+ buf[n] = 0x80 | uint8(x);
+ nn, err := w.Write(buf[0:n+1]);
+ return err;
+}
+
+// EncodeInt writes an encoded signed integer to w.
+// The low bit of the encoding says whether to bit complement the (other bits of the) uint to recover the int.
+func EncodeInt(w io.Writer, i int64) os.Error {
+ var x uint64;
+ if i < 0 {
+ x = uint64(^i << 1) | 1
+ } else {
+ x = uint64(i << 1)
+ }
+ return EncodeUint(w, uint64(x))
+}
diff --git a/src/pkg/gob/type_test.go b/src/pkg/gob/type_test.go
index a2efee9ba..f07bdf36a 100644
--- a/src/pkg/gob/type_test.go
+++ b/src/pkg/gob/type_test.go
@@ -5,21 +5,11 @@
package gob
import (
-"fmt";
"gob";
"os";
"testing";
)
-func checkType(ti Type, expected string, t *testing.T) {
- if ti.String() != expected {
- t.Errorf("checkType: expected %q got %s", expected, ti.String())
- }
- if ti.id() == 0 {
- t.Errorf("id for %q is zero", expected)
- }
-}
-
type typeT struct {
typ Type;
str string;