Ver Fonte

Add comment filter for config

世界 há 3 anos atrás
pai
commit
87bc292296
2 ficheiros alterados com 129 adições e 1 exclusões
  1. 128 0
      common/json/comment.go
  2. 1 1
      option/config.go

+ 128 - 0
common/json/comment.go

@@ -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
+}

+ 1 - 1
option/config.go

@@ -20,7 +20,7 @@ type _Options struct {
 type Options _Options
 type Options _Options
 
 
 func (o *Options) UnmarshalJSON(content []byte) error {
 func (o *Options) UnmarshalJSON(content []byte) error {
-	decoder := json.NewDecoder(bytes.NewReader(content))
+	decoder := json.NewDecoder(json.NewCommentFilter(bytes.NewReader(content)))
 	decoder.DisallowUnknownFields()
 	decoder.DisallowUnknownFields()
 	err := decoder.Decode((*_Options)(o))
 	err := decoder.Decode((*_Options)(o))
 	if err == nil {
 	if err == nil {