2016-12-14 22:51:03 +00:00
|
|
|
package json
|
|
|
|
|
|
|
|
import (
|
|
|
|
"io"
|
|
|
|
)
|
|
|
|
|
2016-12-15 14:53:23 +00:00
|
|
|
// State is the internal state of parser.
|
2016-12-14 22:51:03 +00:00
|
|
|
type State byte
|
|
|
|
|
|
|
|
const (
|
2016-12-14 23:00:44 +00:00
|
|
|
StateContent State = iota
|
|
|
|
StateEscape
|
|
|
|
StateDoubleQuote
|
|
|
|
StateDoubleQuoteEscape
|
|
|
|
StateSingleQuote
|
|
|
|
StateSingleQuoteEscape
|
|
|
|
StateComment
|
|
|
|
StateSlash
|
|
|
|
StateMultilineComment
|
|
|
|
StateMultilineCommentStar
|
2016-12-14 22:51:03 +00:00
|
|
|
)
|
|
|
|
|
2016-12-15 14:55:31 +00:00
|
|
|
// Reader is a JSON reader which allows comments.
|
2016-12-14 22:51:03 +00:00
|
|
|
type Reader struct {
|
|
|
|
io.Reader
|
|
|
|
state State
|
|
|
|
}
|
|
|
|
|
2016-12-15 14:55:31 +00:00
|
|
|
// Read implements io.Reader.Read().
|
2016-12-14 22:51:03 +00:00
|
|
|
func (v *Reader) Read(b []byte) (int, error) {
|
|
|
|
n, err := v.Reader.Read(b)
|
|
|
|
if err != nil {
|
|
|
|
return n, err
|
|
|
|
}
|
|
|
|
p := b[:0]
|
|
|
|
for _, x := range b[:n] {
|
|
|
|
switch v.state {
|
|
|
|
case StateContent:
|
|
|
|
switch x {
|
|
|
|
case '"':
|
|
|
|
v.state = StateDoubleQuote
|
|
|
|
p = append(p, x)
|
|
|
|
case '\'':
|
|
|
|
v.state = StateSingleQuote
|
|
|
|
p = append(p, x)
|
|
|
|
case '\\':
|
|
|
|
v.state = StateEscape
|
|
|
|
case '#':
|
|
|
|
v.state = StateComment
|
|
|
|
case '/':
|
|
|
|
v.state = StateSlash
|
|
|
|
default:
|
|
|
|
p = append(p, x)
|
|
|
|
}
|
|
|
|
case StateEscape:
|
2016-12-15 14:53:23 +00:00
|
|
|
p = append(p, '\\', x)
|
2016-12-14 22:51:03 +00:00
|
|
|
v.state = StateContent
|
|
|
|
case StateDoubleQuote:
|
2016-12-14 23:00:44 +00:00
|
|
|
switch x {
|
|
|
|
case '"':
|
2016-12-14 22:51:03 +00:00
|
|
|
v.state = StateContent
|
2016-12-14 23:00:44 +00:00
|
|
|
p = append(p, x)
|
|
|
|
case '\\':
|
|
|
|
v.state = StateDoubleQuoteEscape
|
|
|
|
default:
|
|
|
|
p = append(p, x)
|
2016-12-14 22:51:03 +00:00
|
|
|
}
|
2016-12-14 23:00:44 +00:00
|
|
|
case StateDoubleQuoteEscape:
|
|
|
|
p = append(p, '\\', x)
|
|
|
|
v.state = StateDoubleQuote
|
2016-12-14 22:51:03 +00:00
|
|
|
case StateSingleQuote:
|
2016-12-14 23:00:44 +00:00
|
|
|
switch x {
|
|
|
|
case '\'':
|
2016-12-14 22:51:03 +00:00
|
|
|
v.state = StateContent
|
2016-12-14 23:00:44 +00:00
|
|
|
p = append(p, x)
|
|
|
|
case '\\':
|
|
|
|
v.state = StateSingleQuoteEscape
|
|
|
|
default:
|
|
|
|
p = append(p, x)
|
2016-12-14 22:51:03 +00:00
|
|
|
}
|
2016-12-14 23:00:44 +00:00
|
|
|
case StateSingleQuoteEscape:
|
|
|
|
p = append(p, '\\', x)
|
|
|
|
v.state = StateSingleQuote
|
2016-12-14 22:51:03 +00:00
|
|
|
case StateComment:
|
|
|
|
if x == '\n' {
|
|
|
|
v.state = StateContent
|
|
|
|
}
|
|
|
|
case StateSlash:
|
|
|
|
switch x {
|
|
|
|
case '/':
|
|
|
|
v.state = StateComment
|
|
|
|
case '*':
|
|
|
|
v.state = StateMultilineComment
|
|
|
|
default:
|
|
|
|
p = append(p, '/', x)
|
|
|
|
}
|
|
|
|
case StateMultilineComment:
|
|
|
|
if x == '*' {
|
|
|
|
v.state = StateMultilineCommentStar
|
|
|
|
}
|
|
|
|
case StateMultilineCommentStar:
|
|
|
|
switch x {
|
|
|
|
case '/':
|
|
|
|
v.state = StateContent
|
|
|
|
case '*':
|
|
|
|
// Stay
|
|
|
|
default:
|
|
|
|
v.state = StateMultilineComment
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
panic("Unknown state.")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return len(p), nil
|
|
|
|
}
|