Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
go
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
go
Commits
60dddc6d
Commit
60dddc6d
authored
Jun 02, 2011
by
Rob Pike
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fmt: return EOF when out of input in Scan*.
Fixes #1840. R=rsc CC=golang-dev
https://golang.org/cl/4548077
parent
bc3a72fa
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
91 additions
and
11 deletions
+91
-11
src/pkg/fmt/scan.go
src/pkg/fmt/scan.go
+29
-11
src/pkg/fmt/scan_test.go
src/pkg/fmt/scan_test.go
+62
-0
No files found.
src/pkg/fmt/scan.go
View file @
60dddc6d
...
...
@@ -466,6 +466,14 @@ func (s *ss) peek(ok string) bool {
return
strings
.
IndexRune
(
ok
,
rune
)
>=
0
}
func
(
s
*
ss
)
notEOF
()
{
// Guarantee there is data to be read.
if
rune
:=
s
.
getRune
();
rune
==
eof
{
panic
(
os
.
EOF
)
}
s
.
UnreadRune
()
}
// accept checks the next rune in the input. If it's a byte (sic) in the string, it puts it in the
// buffer and returns true. Otherwise it return false.
func
(
s
*
ss
)
accept
(
ok
string
)
bool
{
...
...
@@ -485,11 +493,13 @@ func (s *ss) okVerb(verb int, okVerbs, typ string) bool {
// scanBool returns the value of the boolean represented by the next token.
func
(
s
*
ss
)
scanBool
(
verb
int
)
bool
{
s
.
skipSpace
(
false
)
s
.
notEOF
()
if
!
s
.
okVerb
(
verb
,
"tv"
,
"boolean"
)
{
return
false
}
// Syntax-checking a boolean is annoying. We're not fastidious about case.
switch
s
.
mustRead
Rune
()
{
switch
s
.
get
Rune
()
{
case
'0'
:
return
false
case
'1'
:
...
...
@@ -540,6 +550,7 @@ func (s *ss) getBase(verb int) (base int, digits string) {
// scanNumber returns the numerical string with specified digits starting here.
func
(
s
*
ss
)
scanNumber
(
digits
string
,
haveDigits
bool
)
string
{
s
.
notEOF
()
if
!
haveDigits
&&
!
s
.
accept
(
digits
)
{
s
.
errorString
(
"expected integer"
)
}
...
...
@@ -550,7 +561,8 @@ func (s *ss) scanNumber(digits string, haveDigits bool) string {
// scanRune returns the next rune value in the input.
func
(
s
*
ss
)
scanRune
(
bitSize
int
)
int64
{
rune
:=
int64
(
s
.
mustReadRune
())
s
.
notEOF
()
rune
:=
int64
(
s
.
getRune
())
n
:=
uint
(
bitSize
)
x
:=
(
rune
<<
(
64
-
n
))
>>
(
64
-
n
)
if
x
!=
rune
{
...
...
@@ -584,6 +596,7 @@ func (s *ss) scanInt(verb int, bitSize int) int64 {
return
s
.
scanRune
(
bitSize
)
}
s
.
skipSpace
(
false
)
s
.
notEOF
()
base
,
digits
:=
s
.
getBase
(
verb
)
haveDigits
:=
false
if
verb
==
'U'
{
...
...
@@ -616,6 +629,7 @@ func (s *ss) scanUint(verb int, bitSize int) uint64 {
return
uint64
(
s
.
scanRune
(
bitSize
))
}
s
.
skipSpace
(
false
)
s
.
notEOF
()
base
,
digits
:=
s
.
getBase
(
verb
)
haveDigits
:=
false
if
verb
==
'U'
{
...
...
@@ -736,6 +750,7 @@ func (s *ss) scanComplex(verb int, n int) complex128 {
return
0
}
s
.
skipSpace
(
false
)
s
.
notEOF
()
sreal
,
simag
:=
s
.
complexTokens
()
real
:=
s
.
convertFloat
(
sreal
,
n
/
2
)
imag
:=
s
.
convertFloat
(
simag
,
n
/
2
)
...
...
@@ -749,6 +764,7 @@ func (s *ss) convertString(verb int) (str string) {
return
""
}
s
.
skipSpace
(
false
)
s
.
notEOF
()
switch
verb
{
case
'q'
:
str
=
s
.
quotedString
()
...
...
@@ -757,16 +773,13 @@ func (s *ss) convertString(verb int) (str string) {
default
:
str
=
string
(
s
.
token
(
true
,
notSpace
))
// %s and %v just return the next word
}
// Empty strings other than with %q are not OK.
if
len
(
str
)
==
0
&&
verb
!=
'q'
&&
s
.
maxWid
>
0
{
s
.
errorString
(
"Scan: no data for string"
)
}
return
}
// quotedString returns the double- or back-quoted string represented by the next input characters.
func
(
s
*
ss
)
quotedString
()
string
{
quote
:=
s
.
mustReadRune
()
s
.
notEOF
()
quote
:=
s
.
getRune
()
switch
quote
{
case
'`'
:
// Back-quoted: Anything goes until EOF or back quote.
...
...
@@ -836,6 +849,7 @@ func (s *ss) hexByte() (b byte, ok bool) {
// hexString returns the space-delimited hexpair-encoded string.
func
(
s
*
ss
)
hexString
()
string
{
s
.
notEOF
()
for
{
b
,
ok
:=
s
.
hexByte
()
if
!
ok
{
...
...
@@ -869,6 +883,7 @@ func (s *ss) scanOne(verb int, field interface{}) {
}
return
}
switch
v
:=
field
.
(
type
)
{
case
*
bool
:
*
v
=
s
.
scanBool
(
verb
)
...
...
@@ -903,11 +918,13 @@ func (s *ss) scanOne(verb int, field interface{}) {
case
*
float32
:
if
s
.
okVerb
(
verb
,
floatVerbs
,
"float32"
)
{
s
.
skipSpace
(
false
)
s
.
notEOF
()
*
v
=
float32
(
s
.
convertFloat
(
s
.
floatToken
(),
32
))
}
case
*
float64
:
if
s
.
okVerb
(
verb
,
floatVerbs
,
"float64"
)
{
s
.
skipSpace
(
false
)
s
.
notEOF
()
*
v
=
s
.
convertFloat
(
s
.
floatToken
(),
64
)
}
case
*
string
:
...
...
@@ -945,6 +962,7 @@ func (s *ss) scanOne(verb int, field interface{}) {
}
case
reflect
.
Float32
,
reflect
.
Float64
:
s
.
skipSpace
(
false
)
s
.
notEOF
()
v
.
SetFloat
(
s
.
convertFloat
(
s
.
floatToken
(),
v
.
Type
()
.
Bits
()))
case
reflect
.
Complex64
,
reflect
.
Complex128
:
v
.
SetComplex
(
s
.
scanComplex
(
verb
,
v
.
Type
()
.
Bits
()))
...
...
@@ -955,13 +973,13 @@ func (s *ss) scanOne(verb int, field interface{}) {
}
}
// errorHandler turns local panics into error returns.
EOFs are benign.
// errorHandler turns local panics into error returns.
func
errorHandler
(
errp
*
os
.
Error
)
{
if
e
:=
recover
();
e
!=
nil
{
if
se
,
ok
:=
e
.
(
scanError
);
ok
{
// catch local error
if
se
.
err
!=
os
.
EOF
{
*
errp
=
se
.
err
}
*
errp
=
se
.
err
}
else
if
eof
,
ok
:=
e
.
(
os
.
Error
);
ok
&&
eof
==
os
.
EOF
{
// out of input
*
errp
=
eof
}
else
{
panic
(
e
)
}
...
...
src/pkg/fmt/scan_test.go
View file @
60dddc6d
...
...
@@ -660,6 +660,68 @@ func TestEOF(t *testing.T) {
}
}
// Verify that we see an EOF error if we run out of input.
// This was a buglet: we used to get "expected integer".
func
TestEOFAtEndOfInput
(
t
*
testing
.
T
)
{
var
i
,
j
int
n
,
err
:=
Sscanf
(
"23"
,
"%d %d"
,
&
i
,
&
j
)
if
n
!=
1
||
i
!=
23
{
t
.
Errorf
(
"Sscanf expected one value of 23; got %d %d"
,
n
,
i
)
}
if
err
!=
os
.
EOF
{
t
.
Errorf
(
"Sscanf expected EOF; got %q"
,
err
)
}
n
,
err
=
Sscan
(
"234"
,
&
i
,
&
j
)
if
n
!=
1
||
i
!=
234
{
t
.
Errorf
(
"Sscan expected one value of 234; got %d %d"
,
n
,
i
)
}
if
err
!=
os
.
EOF
{
t
.
Errorf
(
"Sscan expected EOF; got %q"
,
err
)
}
// Trailing space is tougher.
n
,
err
=
Sscan
(
"234 "
,
&
i
,
&
j
)
if
n
!=
1
||
i
!=
234
{
t
.
Errorf
(
"Sscan expected one value of 234; got %d %d"
,
n
,
i
)
}
if
err
!=
os
.
EOF
{
t
.
Errorf
(
"Sscan expected EOF; got %q"
,
err
)
}
}
var
eofTests
=
[]
struct
{
format
string
v
interface
{}
}{
{
"%s"
,
&
stringVal
},
{
"%q"
,
&
stringVal
},
{
"%x"
,
&
stringVal
},
{
"%v"
,
&
stringVal
},
{
"%v"
,
&
bytesVal
},
{
"%v"
,
&
intVal
},
{
"%v"
,
&
uintVal
},
{
"%v"
,
&
boolVal
},
{
"%v"
,
&
float32Val
},
{
"%v"
,
&
complex64Val
},
{
"%v"
,
&
renamedStringVal
},
{
"%v"
,
&
renamedBytesVal
},
{
"%v"
,
&
renamedIntVal
},
{
"%v"
,
&
renamedUintVal
},
{
"%v"
,
&
renamedBoolVal
},
{
"%v"
,
&
renamedFloat32Val
},
{
"%v"
,
&
renamedComplex64Val
},
}
func
TestEOFAllTypes
(
t
*
testing
.
T
)
{
for
i
,
test
:=
range
eofTests
{
if
_
,
err
:=
Sscanf
(
""
,
test
.
format
,
test
.
v
);
err
!=
os
.
EOF
{
t
.
Errorf
(
"#%d: %s %T not eof on empty string: %s"
,
i
,
test
.
format
,
test
.
v
,
err
)
}
if
_
,
err
:=
Sscanf
(
" "
,
test
.
format
,
test
.
v
);
err
!=
os
.
EOF
{
t
.
Errorf
(
"#%d: %s %T not eof on trailing blanks: %s"
,
i
,
test
.
format
,
test
.
v
,
err
)
}
}
}
// Verify that, at least when using bufio, successive calls to Fscan do not lose runes.
func
TestUnreadRuneWithBufio
(
t
*
testing
.
T
)
{
r
:=
bufio
.
NewReader
(
strings
.
NewReader
(
"123αb"
))
...
...
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