|
@@ -0,0 +1,128 @@
|
|
|
+package json
|
|
|
+
|
|
|
+import (
|
|
|
+ "bufio"
|
|
|
+ "io"
|
|
|
+)
|
|
|
+
|
|
|
+// kanged from v2ray
|
|
|
+
|
|
|
+type commentFilterState = byte
|
|
|
+
|
|
|
+const (
|
|
|
+ commentFilterStateContent commentFilterState = iota
|
|
|
+ commentFilterStateEscape
|
|
|
+ commentFilterStateDoubleQuote
|
|
|
+ commentFilterStateDoubleQuoteEscape
|
|
|
+ commentFilterStateSingleQuote
|
|
|
+ commentFilterStateSingleQuoteEscape
|
|
|
+ commentFilterStateComment
|
|
|
+ commentFilterStateSlash
|
|
|
+ commentFilterStateMultilineComment
|
|
|
+ commentFilterStateMultilineCommentStar
|
|
|
+)
|
|
|
+
|
|
|
+type CommentFilter struct {
|
|
|
+ br *bufio.Reader
|
|
|
+ state commentFilterState
|
|
|
+}
|
|
|
+
|
|
|
+func NewCommentFilter(reader io.Reader) io.Reader {
|
|
|
+ return &CommentFilter{br: bufio.NewReader(reader)}
|
|
|
+}
|
|
|
+
|
|
|
+func (v *CommentFilter) Read(b []byte) (int, error) {
|
|
|
+ p := b[:0]
|
|
|
+ for len(p) < len(b)-2 {
|
|
|
+ x, err := v.br.ReadByte()
|
|
|
+ if err != nil {
|
|
|
+ if len(p) == 0 {
|
|
|
+ return 0, err
|
|
|
+ }
|
|
|
+ return len(p), nil
|
|
|
+ }
|
|
|
+ switch v.state {
|
|
|
+ case commentFilterStateContent:
|
|
|
+ switch x {
|
|
|
+ case '"':
|
|
|
+ v.state = commentFilterStateDoubleQuote
|
|
|
+ p = append(p, x)
|
|
|
+ case '\'':
|
|
|
+ v.state = commentFilterStateSingleQuote
|
|
|
+ p = append(p, x)
|
|
|
+ case '\\':
|
|
|
+ v.state = commentFilterStateEscape
|
|
|
+ case '#':
|
|
|
+ v.state = commentFilterStateComment
|
|
|
+ case '/':
|
|
|
+ v.state = commentFilterStateSlash
|
|
|
+ default:
|
|
|
+ p = append(p, x)
|
|
|
+ }
|
|
|
+ case commentFilterStateEscape:
|
|
|
+ p = append(p, '\\', x)
|
|
|
+ v.state = commentFilterStateContent
|
|
|
+ case commentFilterStateDoubleQuote:
|
|
|
+ switch x {
|
|
|
+ case '"':
|
|
|
+ v.state = commentFilterStateContent
|
|
|
+ p = append(p, x)
|
|
|
+ case '\\':
|
|
|
+ v.state = commentFilterStateDoubleQuoteEscape
|
|
|
+ default:
|
|
|
+ p = append(p, x)
|
|
|
+ }
|
|
|
+ case commentFilterStateDoubleQuoteEscape:
|
|
|
+ p = append(p, '\\', x)
|
|
|
+ v.state = commentFilterStateDoubleQuote
|
|
|
+ case commentFilterStateSingleQuote:
|
|
|
+ switch x {
|
|
|
+ case '\'':
|
|
|
+ v.state = commentFilterStateContent
|
|
|
+ p = append(p, x)
|
|
|
+ case '\\':
|
|
|
+ v.state = commentFilterStateSingleQuoteEscape
|
|
|
+ default:
|
|
|
+ p = append(p, x)
|
|
|
+ }
|
|
|
+ case commentFilterStateSingleQuoteEscape:
|
|
|
+ p = append(p, '\\', x)
|
|
|
+ v.state = commentFilterStateSingleQuote
|
|
|
+ case commentFilterStateComment:
|
|
|
+ if x == '\n' {
|
|
|
+ v.state = commentFilterStateContent
|
|
|
+ p = append(p, '\n')
|
|
|
+ }
|
|
|
+ case commentFilterStateSlash:
|
|
|
+ switch x {
|
|
|
+ case '/':
|
|
|
+ v.state = commentFilterStateComment
|
|
|
+ case '*':
|
|
|
+ v.state = commentFilterStateMultilineComment
|
|
|
+ default:
|
|
|
+ p = append(p, '/', x)
|
|
|
+ }
|
|
|
+ case commentFilterStateMultilineComment:
|
|
|
+ switch x {
|
|
|
+ case '*':
|
|
|
+ v.state = commentFilterStateMultilineCommentStar
|
|
|
+ case '\n':
|
|
|
+ p = append(p, '\n')
|
|
|
+ }
|
|
|
+ case commentFilterStateMultilineCommentStar:
|
|
|
+ switch x {
|
|
|
+ case '/':
|
|
|
+ v.state = commentFilterStateContent
|
|
|
+ case '*':
|
|
|
+ // Stay
|
|
|
+ case '\n':
|
|
|
+ p = append(p, '\n')
|
|
|
+ default:
|
|
|
+ v.state = commentFilterStateMultilineComment
|
|
|
+ }
|
|
|
+ default:
|
|
|
+ panic("Unknown state.")
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return len(p), nil
|
|
|
+}
|