Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
G
golang
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
go
golang
Commits
415545e5
Commit
415545e5
authored
Dec 06, 2010
by
Roger Peppe
Committed by
Rob Pike
Dec 06, 2010
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
bytes: add Buffer.UnreadRune, Buffer.UnreadByte
R=rsc, r CC=golang-dev
https://golang.org/cl/3421041
parent
dfd98d09
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
80 additions
and
4 deletions
+80
-4
buffer.go
src/pkg/bytes/buffer.go
+61
-0
buffer_test.go
src/pkg/bytes/buffer_test.go
+19
-4
No files found.
src/pkg/bytes/buffer.go
View file @
415545e5
...
@@ -19,8 +19,20 @@ type Buffer struct {
...
@@ -19,8 +19,20 @@ type Buffer struct {
off
int
// read at &buf[off], write at &buf[len(buf)]
off
int
// read at &buf[off], write at &buf[len(buf)]
runeBytes
[
utf8
.
UTFMax
]
byte
// avoid allocation of slice on each WriteByte or Rune
runeBytes
[
utf8
.
UTFMax
]
byte
// avoid allocation of slice on each WriteByte or Rune
bootstrap
[
64
]
byte
// memory to hold first slice; helps small buffers (Printf) avoid allocation.
bootstrap
[
64
]
byte
// memory to hold first slice; helps small buffers (Printf) avoid allocation.
lastRead
readOp
// last read operation, so that Unread* can work correctly.
}
}
// The readOp constants describe the last action performed on
// the buffer, so that UnreadRune and UnreadByte can
// check for invalid usage.
type
readOp
int
const
(
opInvalid
readOp
=
iota
// Non-read operation.
opReadRune
// Read rune.
opRead
// Any other read operation.
)
// Bytes returns a slice of the contents of the unread portion of the buffer;
// Bytes returns a slice of the contents of the unread portion of the buffer;
// len(b.Bytes()) == b.Len(). If the caller changes the contents of the
// len(b.Bytes()) == b.Len(). If the caller changes the contents of the
// returned slice, the contents of the buffer will change provided there
// returned slice, the contents of the buffer will change provided there
...
@@ -44,6 +56,7 @@ func (b *Buffer) Len() int { return len(b.buf) - b.off }
...
@@ -44,6 +56,7 @@ func (b *Buffer) Len() int { return len(b.buf) - b.off }
// Truncate discards all but the first n unread bytes from the buffer.
// Truncate discards all but the first n unread bytes from the buffer.
// It is an error to call b.Truncate(n) with n > b.Len().
// It is an error to call b.Truncate(n) with n > b.Len().
func
(
b
*
Buffer
)
Truncate
(
n
int
)
{
func
(
b
*
Buffer
)
Truncate
(
n
int
)
{
b
.
lastRead
=
opInvalid
if
n
==
0
{
if
n
==
0
{
// Reuse buffer space.
// Reuse buffer space.
b
.
off
=
0
b
.
off
=
0
...
@@ -82,6 +95,7 @@ func (b *Buffer) grow(n int) int {
...
@@ -82,6 +95,7 @@ func (b *Buffer) grow(n int) int {
// Write appends the contents of p to the buffer. The return
// Write appends the contents of p to the buffer. The return
// value n is the length of p; err is always nil.
// value n is the length of p; err is always nil.
func
(
b
*
Buffer
)
Write
(
p
[]
byte
)
(
n
int
,
err
os
.
Error
)
{
func
(
b
*
Buffer
)
Write
(
p
[]
byte
)
(
n
int
,
err
os
.
Error
)
{
b
.
lastRead
=
opInvalid
m
:=
b
.
grow
(
len
(
p
))
m
:=
b
.
grow
(
len
(
p
))
copy
(
b
.
buf
[
m
:
],
p
)
copy
(
b
.
buf
[
m
:
],
p
)
return
len
(
p
),
nil
return
len
(
p
),
nil
...
@@ -90,6 +104,7 @@ func (b *Buffer) Write(p []byte) (n int, err os.Error) {
...
@@ -90,6 +104,7 @@ func (b *Buffer) Write(p []byte) (n int, err os.Error) {
// WriteString appends the contents of s to the buffer. The return
// WriteString appends the contents of s to the buffer. The return
// value n is the length of s; err is always nil.
// value n is the length of s; err is always nil.
func
(
b
*
Buffer
)
WriteString
(
s
string
)
(
n
int
,
err
os
.
Error
)
{
func
(
b
*
Buffer
)
WriteString
(
s
string
)
(
n
int
,
err
os
.
Error
)
{
b
.
lastRead
=
opInvalid
m
:=
b
.
grow
(
len
(
s
))
m
:=
b
.
grow
(
len
(
s
))
return
copy
(
b
.
buf
[
m
:
],
s
),
nil
return
copy
(
b
.
buf
[
m
:
],
s
),
nil
}
}
...
@@ -105,6 +120,7 @@ const MinRead = 512
...
@@ -105,6 +120,7 @@ const MinRead = 512
// Any error except os.EOF encountered during the read
// Any error except os.EOF encountered during the read
// is also returned.
// is also returned.
func
(
b
*
Buffer
)
ReadFrom
(
r
io
.
Reader
)
(
n
int64
,
err
os
.
Error
)
{
func
(
b
*
Buffer
)
ReadFrom
(
r
io
.
Reader
)
(
n
int64
,
err
os
.
Error
)
{
b
.
lastRead
=
opInvalid
// If buffer is empty, reset to recover space.
// If buffer is empty, reset to recover space.
if
b
.
off
>=
len
(
b
.
buf
)
{
if
b
.
off
>=
len
(
b
.
buf
)
{
b
.
Truncate
(
0
)
b
.
Truncate
(
0
)
...
@@ -141,6 +157,7 @@ func (b *Buffer) ReadFrom(r io.Reader) (n int64, err os.Error) {
...
@@ -141,6 +157,7 @@ func (b *Buffer) ReadFrom(r io.Reader) (n int64, err os.Error) {
// occurs. The return value n is the number of bytes written.
// occurs. The return value n is the number of bytes written.
// Any error encountered during the write is also returned.
// Any error encountered during the write is also returned.
func
(
b
*
Buffer
)
WriteTo
(
w
io
.
Writer
)
(
n
int64
,
err
os
.
Error
)
{
func
(
b
*
Buffer
)
WriteTo
(
w
io
.
Writer
)
(
n
int64
,
err
os
.
Error
)
{
b
.
lastRead
=
opInvalid
for
b
.
off
<
len
(
b
.
buf
)
{
for
b
.
off
<
len
(
b
.
buf
)
{
m
,
e
:=
w
.
Write
(
b
.
buf
[
b
.
off
:
])
m
,
e
:=
w
.
Write
(
b
.
buf
[
b
.
off
:
])
n
+=
int64
(
m
)
n
+=
int64
(
m
)
...
@@ -158,6 +175,7 @@ func (b *Buffer) WriteTo(w io.Writer) (n int64, err os.Error) {
...
@@ -158,6 +175,7 @@ func (b *Buffer) WriteTo(w io.Writer) (n int64, err os.Error) {
// The returned error is always nil, but is included
// The returned error is always nil, but is included
// to match bufio.Writer's WriteByte.
// to match bufio.Writer's WriteByte.
func
(
b
*
Buffer
)
WriteByte
(
c
byte
)
os
.
Error
{
func
(
b
*
Buffer
)
WriteByte
(
c
byte
)
os
.
Error
{
b
.
lastRead
=
opInvalid
m
:=
b
.
grow
(
1
)
m
:=
b
.
grow
(
1
)
b
.
buf
[
m
]
=
c
b
.
buf
[
m
]
=
c
return
nil
return
nil
...
@@ -182,6 +200,7 @@ func (b *Buffer) WriteRune(r int) (n int, err os.Error) {
...
@@ -182,6 +200,7 @@ func (b *Buffer) WriteRune(r int) (n int, err os.Error) {
// buffer has no data to return, err is os.EOF even if len(p) is zero;
// buffer has no data to return, err is os.EOF even if len(p) is zero;
// otherwise it is nil.
// otherwise it is nil.
func
(
b
*
Buffer
)
Read
(
p
[]
byte
)
(
n
int
,
err
os
.
Error
)
{
func
(
b
*
Buffer
)
Read
(
p
[]
byte
)
(
n
int
,
err
os
.
Error
)
{
b
.
lastRead
=
opInvalid
if
b
.
off
>=
len
(
b
.
buf
)
{
if
b
.
off
>=
len
(
b
.
buf
)
{
// Buffer is empty, reset to recover space.
// Buffer is empty, reset to recover space.
b
.
Truncate
(
0
)
b
.
Truncate
(
0
)
...
@@ -189,6 +208,9 @@ func (b *Buffer) Read(p []byte) (n int, err os.Error) {
...
@@ -189,6 +208,9 @@ func (b *Buffer) Read(p []byte) (n int, err os.Error) {
}
}
n
=
copy
(
p
,
b
.
buf
[
b
.
off
:
])
n
=
copy
(
p
,
b
.
buf
[
b
.
off
:
])
b
.
off
+=
n
b
.
off
+=
n
if
n
>
0
{
b
.
lastRead
=
opRead
}
return
return
}
}
...
@@ -197,18 +219,23 @@ func (b *Buffer) Read(p []byte) (n int, err os.Error) {
...
@@ -197,18 +219,23 @@ func (b *Buffer) Read(p []byte) (n int, err os.Error) {
// If there are fewer than n bytes in the buffer, Next returns the entire buffer.
// If there are fewer than n bytes in the buffer, Next returns the entire buffer.
// The slice is only valid until the next call to a read or write method.
// The slice is only valid until the next call to a read or write method.
func
(
b
*
Buffer
)
Next
(
n
int
)
[]
byte
{
func
(
b
*
Buffer
)
Next
(
n
int
)
[]
byte
{
b
.
lastRead
=
opInvalid
m
:=
b
.
Len
()
m
:=
b
.
Len
()
if
n
>
m
{
if
n
>
m
{
n
=
m
n
=
m
}
}
data
:=
b
.
buf
[
b
.
off
:
b
.
off
+
n
]
data
:=
b
.
buf
[
b
.
off
:
b
.
off
+
n
]
b
.
off
+=
n
b
.
off
+=
n
if
n
>
0
{
b
.
lastRead
=
opRead
}
return
data
return
data
}
}
// ReadByte reads and returns the next byte from the buffer.
// ReadByte reads and returns the next byte from the buffer.
// If no byte is available, it returns error os.EOF.
// If no byte is available, it returns error os.EOF.
func
(
b
*
Buffer
)
ReadByte
()
(
c
byte
,
err
os
.
Error
)
{
func
(
b
*
Buffer
)
ReadByte
()
(
c
byte
,
err
os
.
Error
)
{
b
.
lastRead
=
opInvalid
if
b
.
off
>=
len
(
b
.
buf
)
{
if
b
.
off
>=
len
(
b
.
buf
)
{
// Buffer is empty, reset to recover space.
// Buffer is empty, reset to recover space.
b
.
Truncate
(
0
)
b
.
Truncate
(
0
)
...
@@ -216,6 +243,7 @@ func (b *Buffer) ReadByte() (c byte, err os.Error) {
...
@@ -216,6 +243,7 @@ func (b *Buffer) ReadByte() (c byte, err os.Error) {
}
}
c
=
b
.
buf
[
b
.
off
]
c
=
b
.
buf
[
b
.
off
]
b
.
off
++
b
.
off
++
b
.
lastRead
=
opRead
return
c
,
nil
return
c
,
nil
}
}
...
@@ -225,11 +253,13 @@ func (b *Buffer) ReadByte() (c byte, err os.Error) {
...
@@ -225,11 +253,13 @@ func (b *Buffer) ReadByte() (c byte, err os.Error) {
// If the bytes are an erroneous UTF-8 encoding, it
// If the bytes are an erroneous UTF-8 encoding, it
// consumes one byte and returns U+FFFD, 1.
// consumes one byte and returns U+FFFD, 1.
func
(
b
*
Buffer
)
ReadRune
()
(
r
int
,
size
int
,
err
os
.
Error
)
{
func
(
b
*
Buffer
)
ReadRune
()
(
r
int
,
size
int
,
err
os
.
Error
)
{
b
.
lastRead
=
opInvalid
if
b
.
off
>=
len
(
b
.
buf
)
{
if
b
.
off
>=
len
(
b
.
buf
)
{
// Buffer is empty, reset to recover space.
// Buffer is empty, reset to recover space.
b
.
Truncate
(
0
)
b
.
Truncate
(
0
)
return
0
,
0
,
os
.
EOF
return
0
,
0
,
os
.
EOF
}
}
b
.
lastRead
=
opReadRune
c
:=
b
.
buf
[
b
.
off
]
c
:=
b
.
buf
[
b
.
off
]
if
c
<
utf8
.
RuneSelf
{
if
c
<
utf8
.
RuneSelf
{
b
.
off
++
b
.
off
++
...
@@ -240,6 +270,37 @@ func (b *Buffer) ReadRune() (r int, size int, err os.Error) {
...
@@ -240,6 +270,37 @@ func (b *Buffer) ReadRune() (r int, size int, err os.Error) {
return
r
,
n
,
nil
return
r
,
n
,
nil
}
}
// UnreadRune unreads the last rune returned by ReadRune.
// If the most recent read or write operation on the buffer was
// not a ReadRune, UnreadRune returns an error. (In this regard
// it is stricter than UnreadByte, which will unread the last byte
// from any read operation.)
func
(
b
*
Buffer
)
UnreadRune
()
os
.
Error
{
if
b
.
lastRead
!=
opReadRune
{
return
os
.
ErrorString
(
"bytes.Buffer: UnreadRune: previous operation was not ReadRune"
)
}
b
.
lastRead
=
opInvalid
if
b
.
off
>
0
{
_
,
n
:=
utf8
.
DecodeLastRune
(
b
.
buf
[
0
:
b
.
off
])
b
.
off
-=
n
}
return
nil
}
// UnreadByte unreads the last byte returned by the most recent
// read operation. If write has happened since the last read, UnreadByte
// returns an error.
func
(
b
*
Buffer
)
UnreadByte
()
os
.
Error
{
if
b
.
lastRead
==
opReadRune
||
b
.
lastRead
==
opRead
{
return
os
.
ErrorString
(
"bytes.Buffer: UnreadByte: previous operation was not a read"
)
}
b
.
lastRead
=
opInvalid
if
b
.
off
>
0
{
b
.
off
--
}
return
nil
}
// NewBuffer creates and initializes a new Buffer using buf as its initial
// NewBuffer creates and initializes a new Buffer using buf as its initial
// contents. It is intended to prepare a Buffer to read existing data. It
// contents. It is intended to prepare a Buffer to read existing data. It
// can also be used to to size the internal buffer for writing. To do that,
// can also be used to to size the internal buffer for writing. To do that,
...
...
src/pkg/bytes/buffer_test.go
View file @
415545e5
...
@@ -275,10 +275,10 @@ func TestRuneIO(t *testing.T) {
...
@@ -275,10 +275,10 @@ func TestRuneIO(t *testing.T) {
size
:=
utf8
.
EncodeRune
(
b
[
n
:
],
r
)
size
:=
utf8
.
EncodeRune
(
b
[
n
:
],
r
)
nbytes
,
err
:=
buf
.
WriteRune
(
r
)
nbytes
,
err
:=
buf
.
WriteRune
(
r
)
if
err
!=
nil
{
if
err
!=
nil
{
t
.
Fatalf
(
"WriteRune(
0x%
x) error: %s"
,
r
,
err
)
t
.
Fatalf
(
"WriteRune(
U+%.4
x) error: %s"
,
r
,
err
)
}
}
if
nbytes
!=
size
{
if
nbytes
!=
size
{
t
.
Fatalf
(
"WriteRune(
0x%
x) expected %d, got %d"
,
r
,
size
,
nbytes
)
t
.
Fatalf
(
"WriteRune(
U+%.4
x) expected %d, got %d"
,
r
,
size
,
nbytes
)
}
}
n
+=
size
n
+=
size
}
}
...
@@ -289,12 +289,27 @@ func TestRuneIO(t *testing.T) {
...
@@ -289,12 +289,27 @@ func TestRuneIO(t *testing.T) {
t
.
Fatalf
(
"incorrect result from WriteRune: %q not %q"
,
buf
.
Bytes
(),
b
)
t
.
Fatalf
(
"incorrect result from WriteRune: %q not %q"
,
buf
.
Bytes
(),
b
)
}
}
p
:=
make
([]
byte
,
utf8
.
UTFMax
)
// Read it back with ReadRune
// Read it back with ReadRune
for
r
:=
0
;
r
<
NRune
;
r
++
{
for
r
:=
0
;
r
<
NRune
;
r
++
{
size
:=
utf8
.
EncodeRune
(
b
,
r
)
size
:=
utf8
.
EncodeRune
(
p
,
r
)
nr
,
nbytes
,
err
:=
buf
.
ReadRune
()
nr
,
nbytes
,
err
:=
buf
.
ReadRune
()
if
nr
!=
r
||
nbytes
!=
size
||
err
!=
nil
{
if
nr
!=
r
||
nbytes
!=
size
||
err
!=
nil
{
t
.
Fatalf
(
"ReadRune(0x%x) got 0x%x,%d not 0x%x,%d (err=%s)"
,
r
,
nr
,
nbytes
,
r
,
size
,
err
)
t
.
Fatalf
(
"ReadRune(U+%.4x) got U+%.4x,%d not U+%.4x,%d (err=%s)"
,
r
,
nr
,
nbytes
,
r
,
size
,
err
)
}
}
// Check that UnreadRune works
buf
.
Reset
()
buf
.
Write
(
b
)
for
r
:=
0
;
r
<
NRune
;
r
++
{
r1
,
size
,
_
:=
buf
.
ReadRune
()
if
err
:=
buf
.
UnreadRune
();
err
!=
nil
{
t
.
Fatalf
(
"UnreadRune(U+%.4x) got error %q"
,
r
,
err
)
}
r2
,
nbytes
,
err
:=
buf
.
ReadRune
()
if
r1
!=
r2
||
r1
!=
r
||
nbytes
!=
size
||
err
!=
nil
{
t
.
Fatalf
(
"ReadRune(U+%.4x) after UnreadRune got U+%.4x,%d not U+%.4x,%d (err=%s)"
,
r
,
r2
,
nbytes
,
r
,
size
,
err
)
}
}
}
}
}
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment