v2ray-core/tools/conf/json/reader.go

116 lines
2.1 KiB
Go
Raw Normal View History

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
}