aboutsummaryrefslogtreecommitdiff
path: root/libgo/go/encoding
diff options
context:
space:
mode:
Diffstat (limited to 'libgo/go/encoding')
-rw-r--r--libgo/go/encoding/base32/base32_test.go1
-rw-r--r--libgo/go/encoding/base64/base64.go14
-rw-r--r--libgo/go/encoding/base64/base64_test.go9
-rw-r--r--libgo/go/encoding/binary/binary.go102
-rw-r--r--libgo/go/encoding/binary/binary_test.go73
-rw-r--r--libgo/go/encoding/git85/git.go2
-rw-r--r--libgo/go/encoding/hex/hex.go117
-rw-r--r--libgo/go/encoding/hex/hex_test.go43
-rw-r--r--libgo/go/encoding/line/line.go115
-rw-r--r--libgo/go/encoding/line/line_test.go133
-rw-r--r--libgo/go/encoding/pem/pem.go17
11 files changed, 364 insertions, 262 deletions
diff --git a/libgo/go/encoding/base32/base32_test.go b/libgo/go/encoding/base32/base32_test.go
index 792e4dc..3fa1c2b 100644
--- a/libgo/go/encoding/base32/base32_test.go
+++ b/libgo/go/encoding/base32/base32_test.go
@@ -25,7 +25,6 @@ var pairs = []testpair{
{"fooba", "MZXW6YTB"},
{"foobar", "MZXW6YTBOI======"},
-
// Wikipedia examples, converted to base32
{"sure.", "ON2XEZJO"},
{"sure", "ON2XEZI="},
diff --git a/libgo/go/encoding/base64/base64.go b/libgo/go/encoding/base64/base64.go
index 4961297..c6b2a13e 100644
--- a/libgo/go/encoding/base64/base64.go
+++ b/libgo/go/encoding/base64/base64.go
@@ -106,6 +106,13 @@ func (enc *Encoding) Encode(dst, src []byte) {
}
}
+// EncodeToString returns the base64 encoding of src.
+func (enc *Encoding) EncodeToString(src []byte) string {
+ buf := make([]byte, enc.EncodedLen(len(src)))
+ enc.Encode(buf, src)
+ return string(buf)
+}
+
type encoder struct {
err os.Error
enc *Encoding
@@ -260,6 +267,13 @@ func (enc *Encoding) Decode(dst, src []byte) (n int, err os.Error) {
return
}
+// DecodeString returns the bytes represented by the base64 string s.
+func (enc *Encoding) DecodeString(s string) ([]byte, os.Error) {
+ dbuf := make([]byte, enc.DecodedLen(len(s)))
+ n, err := enc.Decode(dbuf, []byte(s))
+ return dbuf[:n], err
+}
+
type decoder struct {
err os.Error
enc *Encoding
diff --git a/libgo/go/encoding/base64/base64_test.go b/libgo/go/encoding/base64/base64_test.go
index de41e70..c163dae 100644
--- a/libgo/go/encoding/base64/base64_test.go
+++ b/libgo/go/encoding/base64/base64_test.go
@@ -56,9 +56,8 @@ func testEqual(t *testing.T, msg string, args ...interface{}) bool {
func TestEncode(t *testing.T) {
for _, p := range pairs {
- buf := make([]byte, StdEncoding.EncodedLen(len(p.decoded)))
- StdEncoding.Encode(buf, []byte(p.decoded))
- testEqual(t, "Encode(%q) = %q, want %q", p.decoded, string(buf), p.encoded)
+ got := StdEncoding.EncodeToString([]byte(p.decoded))
+ testEqual(t, "Encode(%q) = %q, want %q", p.decoded, got, p.encoded)
}
}
@@ -102,6 +101,10 @@ func TestDecode(t *testing.T) {
testEqual(t, "Decode(%q) = end %v, want %v", p.encoded, end, (p.encoded[len(p.encoded)-1] == '='))
}
testEqual(t, "Decode(%q) = %q, want %q", p.encoded, string(dbuf[0:count]), p.decoded)
+
+ dbuf, err = StdEncoding.DecodeString(p.encoded)
+ testEqual(t, "DecodeString(%q) = error %v, want %v", p.encoded, err, os.Error(nil))
+ testEqual(t, "DecodeString(%q) = %q, want %q", string(dbuf), p.decoded)
}
}
diff --git a/libgo/go/encoding/binary/binary.go b/libgo/go/encoding/binary/binary.go
index a01d0e0..8e55cb2 100644
--- a/libgo/go/encoding/binary/binary.go
+++ b/libgo/go/encoding/binary/binary.go
@@ -125,6 +125,35 @@ func (bigEndian) GoString() string { return "binary.BigEndian" }
// Bytes read from r are decoded using the specified byte order
// and written to successive fields of the data.
func Read(r io.Reader, order ByteOrder, data interface{}) os.Error {
+ // Fast path for basic types.
+ if n := intDestSize(data); n != 0 {
+ var b [8]byte
+ bs := b[:n]
+ if _, err := io.ReadFull(r, bs); err != nil {
+ return err
+ }
+ switch v := data.(type) {
+ case *int8:
+ *v = int8(b[0])
+ case *uint8:
+ *v = b[0]
+ case *int16:
+ *v = int16(order.Uint16(bs))
+ case *uint16:
+ *v = order.Uint16(bs)
+ case *int32:
+ *v = int32(order.Uint32(bs))
+ case *uint32:
+ *v = order.Uint32(bs)
+ case *int64:
+ *v = int64(order.Uint64(bs))
+ case *uint64:
+ *v = order.Uint64(bs)
+ }
+ return nil
+ }
+
+ // Fallback to reflect-based.
var v reflect.Value
switch d := reflect.ValueOf(data); d.Kind() {
case reflect.Ptr:
@@ -155,6 +184,63 @@ func Read(r io.Reader, order ByteOrder, data interface{}) os.Error {
// Bytes written to w are encoded using the specified byte order
// and read from successive fields of the data.
func Write(w io.Writer, order ByteOrder, data interface{}) os.Error {
+ // Fast path for basic types.
+ var b [8]byte
+ var bs []byte
+ switch v := data.(type) {
+ case *int8:
+ bs = b[:1]
+ b[0] = byte(*v)
+ case int8:
+ bs = b[:1]
+ b[0] = byte(v)
+ case *uint8:
+ bs = b[:1]
+ b[0] = *v
+ case uint8:
+ bs = b[:1]
+ b[0] = byte(v)
+ case *int16:
+ bs = b[:2]
+ order.PutUint16(bs, uint16(*v))
+ case int16:
+ bs = b[:2]
+ order.PutUint16(bs, uint16(v))
+ case *uint16:
+ bs = b[:2]
+ order.PutUint16(bs, *v)
+ case uint16:
+ bs = b[:2]
+ order.PutUint16(bs, v)
+ case *int32:
+ bs = b[:4]
+ order.PutUint32(bs, uint32(*v))
+ case int32:
+ bs = b[:4]
+ order.PutUint32(bs, uint32(v))
+ case *uint32:
+ bs = b[:4]
+ order.PutUint32(bs, *v)
+ case uint32:
+ bs = b[:4]
+ order.PutUint32(bs, v)
+ case *int64:
+ bs = b[:8]
+ order.PutUint64(bs, uint64(*v))
+ case int64:
+ bs = b[:8]
+ order.PutUint64(bs, uint64(v))
+ case *uint64:
+ bs = b[:8]
+ order.PutUint64(bs, *v)
+ case uint64:
+ bs = b[:8]
+ order.PutUint64(bs, v)
+ }
+ if bs != nil {
+ _, err := w.Write(bs)
+ return err
+ }
v := reflect.Indirect(reflect.ValueOf(data))
size := TotalSize(v)
if size < 0 {
@@ -394,3 +480,19 @@ func (e *encoder) value(v reflect.Value) {
}
}
}
+
+// intDestSize returns the size of the integer that ptrType points to,
+// or 0 if the type is not supported.
+func intDestSize(ptrType interface{}) int {
+ switch ptrType.(type) {
+ case *int8, *uint8:
+ return 1
+ case *int16, *uint16:
+ return 2
+ case *int32, *uint32:
+ return 4
+ case *int64, *uint64:
+ return 8
+ }
+ return 0
+}
diff --git a/libgo/go/encoding/binary/binary_test.go b/libgo/go/encoding/binary/binary_test.go
index 7857c68..b266996 100644
--- a/libgo/go/encoding/binary/binary_test.go
+++ b/libgo/go/encoding/binary/binary_test.go
@@ -5,6 +5,7 @@
package binary
import (
+ "io"
"os"
"bytes"
"math"
@@ -160,3 +161,75 @@ func TestWriteT(t *testing.T) {
}
}
}
+
+type byteSliceReader struct {
+ remain []byte
+}
+
+func (br *byteSliceReader) Read(p []byte) (int, os.Error) {
+ n := copy(p, br.remain)
+ br.remain = br.remain[n:]
+ return n, nil
+}
+
+func BenchmarkRead(b *testing.B) {
+ var ls Struct
+ bsr := &byteSliceReader{}
+ var r io.Reader = bsr
+
+ for i := 0; i < b.N; i++ {
+ bsr.remain = big
+ Read(r, BigEndian, &ls.Int8)
+ Read(r, BigEndian, &ls.Int16)
+ Read(r, BigEndian, &ls.Int32)
+ Read(r, BigEndian, &ls.Int64)
+ Read(r, BigEndian, &ls.Uint8)
+ Read(r, BigEndian, &ls.Uint16)
+ Read(r, BigEndian, &ls.Uint32)
+ Read(r, BigEndian, &ls.Uint64)
+ }
+
+ want := s
+ want.Float32 = 0
+ want.Float64 = 0
+ want.Complex64 = 0
+ want.Complex128 = 0
+ for i := range want.Array {
+ want.Array[i] = 0
+ }
+ if !reflect.DeepEqual(ls, want) {
+ panic("no match")
+ }
+}
+
+func BenchmarkWrite(b *testing.B) {
+ buf := new(bytes.Buffer)
+ var w io.Writer = buf
+
+ for i := 0; i < b.N; i++ {
+ buf.Reset()
+ Write(w, BigEndian, &s.Int8)
+ Write(w, BigEndian, &s.Int16)
+ Write(w, BigEndian, &s.Int32)
+ Write(w, BigEndian, &s.Int64)
+ Write(w, BigEndian, &s.Uint8)
+ Write(w, BigEndian, &s.Uint16)
+ Write(w, BigEndian, &s.Uint32)
+ Write(w, BigEndian, &s.Uint64)
+ Write(w, BigEndian, s.Int8)
+ Write(w, BigEndian, s.Int16)
+ Write(w, BigEndian, s.Int32)
+ Write(w, BigEndian, s.Int64)
+ Write(w, BigEndian, s.Uint8)
+ Write(w, BigEndian, s.Uint16)
+ Write(w, BigEndian, s.Uint32)
+ Write(w, BigEndian, s.Uint64)
+ }
+
+ if !bytes.Equal(buf.Bytes()[:30], big[:30]) {
+ panic("first half doesn't match")
+ }
+ if !bytes.Equal(buf.Bytes()[30:], big[:30]) {
+ panic("second half doesn't match")
+ }
+}
diff --git a/libgo/go/encoding/git85/git.go b/libgo/go/encoding/git85/git.go
index 09a45cd..6bb74f4 100644
--- a/libgo/go/encoding/git85/git.go
+++ b/libgo/go/encoding/git85/git.go
@@ -273,5 +273,5 @@ func (d *decoder) Read(p []byte) (n int, err os.Error) {
d.nbuf = copy(d.buf[0:], d.buf[nl+1:d.nbuf])
d.off += int64(nl + 1)
}
- panic("unreacahable")
+ panic("unreachable")
}
diff --git a/libgo/go/encoding/hex/hex.go b/libgo/go/encoding/hex/hex.go
index 891de18..e7ea8b0 100644
--- a/libgo/go/encoding/hex/hex.go
+++ b/libgo/go/encoding/hex/hex.go
@@ -6,6 +6,8 @@
package hex
import (
+ "bytes"
+ "io"
"os"
"strconv"
)
@@ -40,7 +42,6 @@ func (e InvalidHexCharError) String() string {
return "invalid hex char: " + strconv.Itoa(int(e))
}
-
func DecodedLen(x int) int { return x / 2 }
// Decode decodes src into DecodedLen(len(src)) bytes, returning the actual
@@ -99,3 +100,117 @@ func DecodeString(s string) ([]byte, os.Error) {
}
return dst, nil
}
+
+// Dump returns a string that contains a hex dump of the given data. The format
+// of the hex dump matches the output of `hexdump -C` on the command line.
+func Dump(data []byte) string {
+ buf := bytes.NewBuffer(nil)
+ dumper := Dumper(buf)
+ dumper.Write(data)
+ dumper.Close()
+ return string(buf.Bytes())
+}
+
+// Dumper returns a WriteCloser that writes a hex dump of all written data to
+// w. The format of the dump matches the output of `hexdump -C` on the command
+// line.
+func Dumper(w io.Writer) io.WriteCloser {
+ return &dumper{w: w}
+}
+
+type dumper struct {
+ w io.Writer
+ rightChars [18]byte
+ buf [14]byte
+ used int // number of bytes in the current line
+ n uint // number of bytes, total
+}
+
+func toChar(b byte) byte {
+ if b < 32 || b > 126 {
+ return '.'
+ }
+ return b
+}
+
+func (h *dumper) Write(data []byte) (n int, err os.Error) {
+ // Output lines look like:
+ // 00000010 2e 2f 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d |./0123456789:;<=|
+ // ^ offset ^ extra space ^ ASCII of line.
+ for i := range data {
+ if h.used == 0 {
+ // At the beginning of a line we print the current
+ // offset in hex.
+ h.buf[0] = byte(h.n >> 24)
+ h.buf[1] = byte(h.n >> 16)
+ h.buf[2] = byte(h.n >> 8)
+ h.buf[3] = byte(h.n)
+ Encode(h.buf[4:], h.buf[:4])
+ h.buf[12] = ' '
+ h.buf[13] = ' '
+ _, err = h.w.Write(h.buf[4:])
+ }
+ Encode(h.buf[:], data[i:i+1])
+ h.buf[2] = ' '
+ l := 3
+ if h.used == 7 {
+ // There's an additional space after the 8th byte.
+ h.buf[3] = ' '
+ l = 4
+ } else if h.used == 15 {
+ // At the end of the line there's an extra space and
+ // the bar for the right column.
+ h.buf[3] = ' '
+ h.buf[4] = '|'
+ l = 5
+ }
+ _, err = h.w.Write(h.buf[:l])
+ if err != nil {
+ return
+ }
+ n++
+ h.rightChars[h.used] = toChar(data[i])
+ h.used++
+ h.n++
+ if h.used == 16 {
+ h.rightChars[16] = '|'
+ h.rightChars[17] = '\n'
+ _, err = h.w.Write(h.rightChars[:])
+ if err != nil {
+ return
+ }
+ h.used = 0
+ }
+ }
+ return
+}
+
+func (h *dumper) Close() (err os.Error) {
+ // See the comments in Write() for the details of this format.
+ if h.used == 0 {
+ return
+ }
+ h.buf[0] = ' '
+ h.buf[1] = ' '
+ h.buf[2] = ' '
+ h.buf[3] = ' '
+ h.buf[4] = '|'
+ nBytes := h.used
+ for h.used < 16 {
+ l := 3
+ if h.used == 7 {
+ l = 4
+ } else if h.used == 15 {
+ l = 5
+ }
+ _, err = h.w.Write(h.buf[:l])
+ if err != nil {
+ return
+ }
+ h.used++
+ }
+ h.rightChars[nBytes] = '|'
+ h.rightChars[nBytes+1] = '\n'
+ _, err = h.w.Write(h.rightChars[:nBytes+2])
+ return
+}
diff --git a/libgo/go/encoding/hex/hex_test.go b/libgo/go/encoding/hex/hex_test.go
index a14c9d4..8e1838e 100644
--- a/libgo/go/encoding/hex/hex_test.go
+++ b/libgo/go/encoding/hex/hex_test.go
@@ -147,3 +147,46 @@ func TestDecodeString(t *testing.T) {
}
}
}
+
+func TestDumper(t *testing.T) {
+ var in [40]byte
+ for i := range in {
+ in[i] = byte(i + 30)
+ }
+
+ for stride := 1; stride < len(in); stride++ {
+ out := bytes.NewBuffer(nil)
+ dumper := Dumper(out)
+ done := 0
+ for done < len(in) {
+ todo := done + stride
+ if todo > len(in) {
+ todo = len(in)
+ }
+ dumper.Write(in[done:todo])
+ done = todo
+ }
+
+ dumper.Close()
+ if !bytes.Equal(out.Bytes(), expectedHexDump) {
+ t.Errorf("stride: %d failed. got:\n%s\nwant:\n%s", stride, out.Bytes(), expectedHexDump)
+ }
+ }
+}
+
+func TestDump(t *testing.T) {
+ var in [40]byte
+ for i := range in {
+ in[i] = byte(i + 30)
+ }
+
+ out := []byte(Dump(in[:]))
+ if !bytes.Equal(out, expectedHexDump) {
+ t.Errorf("got:\n%s\nwant:\n%s", out, expectedHexDump)
+ }
+}
+
+var expectedHexDump = []byte(`00000000 1e 1f 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d |.. !"#$%&'()*+,-|
+00000010 2e 2f 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d |./0123456789:;<=|
+00000020 3e 3f 40 41 42 43 44 45 |>?@ABCDE|
+`)
diff --git a/libgo/go/encoding/line/line.go b/libgo/go/encoding/line/line.go
deleted file mode 100644
index 123962b..0000000
--- a/libgo/go/encoding/line/line.go
+++ /dev/null
@@ -1,115 +0,0 @@
-// Copyright 2010 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 line implements a Reader that reads lines delimited by '\n' or
-// ' \r\n'.
-package line
-
-import (
- "io"
- "os"
-)
-
-// Reader reads lines, delimited by '\n' or \r\n', from an io.Reader.
-type Reader struct {
- buf []byte
- consumed int
- in io.Reader
- err os.Error
-}
-
-// NewReader returns a new Reader that will read successive
-// lines from the input Reader.
-func NewReader(input io.Reader, maxLineLength int) *Reader {
- return &Reader{
- buf: make([]byte, 0, maxLineLength),
- consumed: 0,
- in: input,
- }
-}
-
-// Read reads from any buffered data past the last line read, or from the underlying
-// io.Reader if the buffer is empty.
-func (l *Reader) Read(p []byte) (n int, err os.Error) {
- l.removeConsumedFromBuffer()
- if len(l.buf) > 0 {
- n = copy(p, l.buf)
- l.consumed += n
- return
- }
- return l.in.Read(p)
-}
-
-func (l *Reader) removeConsumedFromBuffer() {
- if l.consumed > 0 {
- n := copy(l.buf, l.buf[l.consumed:])
- l.buf = l.buf[:n]
- l.consumed = 0
- }
-}
-
-// ReadLine tries to return a single line, not including the end-of-line bytes.
-// If the line was found to be longer than the maximum length then isPrefix is
-// set and the beginning of the line is returned. The rest of the line will be
-// returned from future calls. isPrefix will be false when returning the last
-// fragment of the line. The returned buffer points into the internal state of
-// the Reader and is only valid until the next call to ReadLine. ReadLine
-// either returns a non-nil line or it returns an error, never both.
-func (l *Reader) ReadLine() (line []byte, isPrefix bool, err os.Error) {
- l.removeConsumedFromBuffer()
-
- if len(l.buf) == 0 && l.err != nil {
- err = l.err
- return
- }
-
- scannedTo := 0
-
- for {
- i := scannedTo
- for ; i < len(l.buf); i++ {
- if l.buf[i] == '\r' && len(l.buf) > i+1 && l.buf[i+1] == '\n' {
- line = l.buf[:i]
- l.consumed = i + 2
- return
- } else if l.buf[i] == '\n' {
- line = l.buf[:i]
- l.consumed = i + 1
- return
- }
- }
-
- if i == cap(l.buf) {
- line = l.buf[:i]
- l.consumed = i
- isPrefix = true
- return
- }
-
- if l.err != nil {
- line = l.buf
- l.consumed = i
- return
- }
-
- // We don't want to rescan the input that we just scanned.
- // However, we need to back up one byte because the last byte
- // could have been a '\r' and we do need to rescan that.
- scannedTo = i
- if scannedTo > 0 {
- scannedTo--
- }
- oldLen := len(l.buf)
- l.buf = l.buf[:cap(l.buf)]
- n, readErr := l.in.Read(l.buf[oldLen:])
- l.buf = l.buf[:oldLen+n]
- if readErr != nil {
- l.err = readErr
- if len(l.buf) == 0 {
- return nil, false, readErr
- }
- }
- }
- panic("unreachable")
-}
diff --git a/libgo/go/encoding/line/line_test.go b/libgo/go/encoding/line/line_test.go
deleted file mode 100644
index ff3d516..0000000
--- a/libgo/go/encoding/line/line_test.go
+++ /dev/null
@@ -1,133 +0,0 @@
-// Copyright 2010 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 line
-
-import (
- "bytes"
- "io"
- "io/ioutil"
- "os"
- "testing"
-)
-
-var testOutput = []byte("0123456789abcdefghijklmnopqrstuvwxy")
-var testInput = []byte("012\n345\n678\n9ab\ncde\nfgh\nijk\nlmn\nopq\nrst\nuvw\nxy")
-var testInputrn = []byte("012\r\n345\r\n678\r\n9ab\r\ncde\r\nfgh\r\nijk\r\nlmn\r\nopq\r\nrst\r\nuvw\r\nxy\r\n\n\r\n")
-
-// TestReader wraps a []byte and returns reads of a specific length.
-type testReader struct {
- data []byte
- stride int
-}
-
-func (t *testReader) Read(buf []byte) (n int, err os.Error) {
- n = t.stride
- if n > len(t.data) {
- n = len(t.data)
- }
- if n > len(buf) {
- n = len(buf)
- }
- copy(buf, t.data)
- t.data = t.data[n:]
- if len(t.data) == 0 {
- err = os.EOF
- }
- return
-}
-
-func testLineReader(t *testing.T, input []byte) {
- for stride := 1; stride < len(input); stride++ {
- done := 0
- reader := testReader{input, stride}
- l := NewReader(&reader, len(input)+1)
- for {
- line, isPrefix, err := l.ReadLine()
- if len(line) > 0 && err != nil {
- t.Errorf("ReadLine returned both data and error: %s", err)
- }
- if isPrefix {
- t.Errorf("ReadLine returned prefix")
- }
- if err != nil {
- if err != os.EOF {
- t.Fatalf("Got unknown error: %s", err)
- }
- break
- }
- if want := testOutput[done : done+len(line)]; !bytes.Equal(want, line) {
- t.Errorf("Bad line at stride %d: want: %x got: %x", stride, want, line)
- }
- done += len(line)
- }
- if done != len(testOutput) {
- t.Error("ReadLine didn't return everything")
- }
- }
-}
-
-func TestReader(t *testing.T) {
- testLineReader(t, testInput)
- testLineReader(t, testInputrn)
-}
-
-func TestLineTooLong(t *testing.T) {
- buf := bytes.NewBuffer([]byte("aaabbbcc\n"))
- l := NewReader(buf, 3)
- line, isPrefix, err := l.ReadLine()
- if !isPrefix || !bytes.Equal(line, []byte("aaa")) || err != nil {
- t.Errorf("bad result for first line: %x %s", line, err)
- }
- line, isPrefix, err = l.ReadLine()
- if !isPrefix || !bytes.Equal(line, []byte("bbb")) || err != nil {
- t.Errorf("bad result for second line: %x", line)
- }
- line, isPrefix, err = l.ReadLine()
- if isPrefix || !bytes.Equal(line, []byte("cc")) || err != nil {
- t.Errorf("bad result for third line: %x", line)
- }
-}
-
-func TestReadAfterLines(t *testing.T) {
- line1 := "line1"
- restData := "line2\nline 3\n"
- inbuf := bytes.NewBuffer([]byte(line1 + "\n" + restData))
- outbuf := new(bytes.Buffer)
- maxLineLength := len(line1) + len(restData)/2
- l := NewReader(inbuf, maxLineLength)
- line, isPrefix, err := l.ReadLine()
- if isPrefix || err != nil || string(line) != line1 {
- t.Errorf("bad result for first line: isPrefix=%v err=%v line=%q", isPrefix, err, string(line))
- }
- n, err := io.Copy(outbuf, l)
- if int(n) != len(restData) || err != nil {
- t.Errorf("bad result for Read: n=%d err=%v", n, err)
- }
- if outbuf.String() != restData {
- t.Errorf("bad result for Read: got %q; expected %q", outbuf.String(), restData)
- }
-}
-
-func TestReadEmptyBuffer(t *testing.T) {
- l := NewReader(bytes.NewBuffer(nil), 10)
- line, isPrefix, err := l.ReadLine()
- if err != os.EOF {
- t.Errorf("expected EOF from ReadLine, got '%s' %t %s", line, isPrefix, err)
- }
-}
-
-func TestLinesAfterRead(t *testing.T) {
- l := NewReader(bytes.NewBuffer([]byte("foo")), 10)
- _, err := ioutil.ReadAll(l)
- if err != nil {
- t.Error(err)
- return
- }
-
- line, isPrefix, err := l.ReadLine()
- if err != os.EOF {
- t.Errorf("expected EOF from ReadLine, got '%s' %t %s", line, isPrefix, err)
- }
-}
diff --git a/libgo/go/encoding/pem/pem.go b/libgo/go/encoding/pem/pem.go
index 44e3d0a..12689b5 100644
--- a/libgo/go/encoding/pem/pem.go
+++ b/libgo/go/encoding/pem/pem.go
@@ -86,7 +86,7 @@ func Decode(data []byte) (p *Block, rest []byte) {
typeLine, rest := getLine(rest)
if !bytes.HasSuffix(typeLine, pemEndOfLine) {
- goto Error
+ return decodeError(data, rest)
}
typeLine = typeLine[0 : len(typeLine)-len(pemEndOfLine)]
@@ -97,7 +97,7 @@ func Decode(data []byte) (p *Block, rest []byte) {
for {
// This loop terminates because getLine's second result is
- // always smaller than it's argument.
+ // always smaller than its argument.
if len(rest) == 0 {
return nil, data
}
@@ -118,29 +118,30 @@ func Decode(data []byte) (p *Block, rest []byte) {
i := bytes.Index(rest, pemEnd)
if i < 0 {
- goto Error
+ return decodeError(data, rest)
}
base64Data := removeWhitespace(rest[0:i])
p.Bytes = make([]byte, base64.StdEncoding.DecodedLen(len(base64Data)))
n, err := base64.StdEncoding.Decode(p.Bytes, base64Data)
if err != nil {
- goto Error
+ return decodeError(data, rest)
}
p.Bytes = p.Bytes[0:n]
_, rest = getLine(rest[i+len(pemEnd):])
return
+}
-Error:
+func decodeError(data, rest []byte) (*Block, []byte) {
// If we get here then we have rejected a likely looking, but
// ultimately invalid PEM block. We need to start over from a new
// position. We have consumed the preamble line and will have consumed
// any lines which could be header lines. However, a valid preamble
// line is not a valid header line, therefore we cannot have consumed
// the preamble line for the any subsequent block. Thus, we will always
- // find any valid block, no matter what bytes preceed it.
+ // find any valid block, no matter what bytes precede it.
//
// For example, if the input is
//
@@ -154,11 +155,11 @@ Error:
//
// we've failed to parse using the first BEGIN line
// and now will try again, using the second BEGIN line.
- p, rest = Decode(rest)
+ p, rest := Decode(rest)
if p == nil {
rest = data
}
- return
+ return p, rest
}
const pemLineLength = 64