github.com/sagernet/sing@v0.4.0-beta.19.0.20240518125136-f67a0988a636/common/json/comment.go (about) 1 package json 2 3 import ( 4 "bufio" 5 "io" 6 ) 7 8 // kanged from v2ray 9 10 type commentFilterState = byte 11 12 const ( 13 commentFilterStateContent commentFilterState = iota 14 commentFilterStateEscape 15 commentFilterStateDoubleQuote 16 commentFilterStateDoubleQuoteEscape 17 commentFilterStateSingleQuote 18 commentFilterStateSingleQuoteEscape 19 commentFilterStateComment 20 commentFilterStateSlash 21 commentFilterStateMultilineComment 22 commentFilterStateMultilineCommentStar 23 ) 24 25 type CommentFilter struct { 26 br *bufio.Reader 27 state commentFilterState 28 } 29 30 func NewCommentFilter(reader io.Reader) io.Reader { 31 return &CommentFilter{br: bufio.NewReader(reader)} 32 } 33 34 func (v *CommentFilter) Read(b []byte) (int, error) { 35 p := b[:0] 36 for len(p) < len(b)-2 { 37 x, err := v.br.ReadByte() 38 if err != nil { 39 if len(p) == 0 { 40 return 0, err 41 } 42 return len(p), nil 43 } 44 switch v.state { 45 case commentFilterStateContent: 46 switch x { 47 case '"': 48 v.state = commentFilterStateDoubleQuote 49 p = append(p, x) 50 case '\'': 51 v.state = commentFilterStateSingleQuote 52 p = append(p, x) 53 case '\\': 54 v.state = commentFilterStateEscape 55 case '#': 56 v.state = commentFilterStateComment 57 case '/': 58 v.state = commentFilterStateSlash 59 default: 60 p = append(p, x) 61 } 62 case commentFilterStateEscape: 63 p = append(p, '\\', x) 64 v.state = commentFilterStateContent 65 case commentFilterStateDoubleQuote: 66 switch x { 67 case '"': 68 v.state = commentFilterStateContent 69 p = append(p, x) 70 case '\\': 71 v.state = commentFilterStateDoubleQuoteEscape 72 default: 73 p = append(p, x) 74 } 75 case commentFilterStateDoubleQuoteEscape: 76 p = append(p, '\\', x) 77 v.state = commentFilterStateDoubleQuote 78 case commentFilterStateSingleQuote: 79 switch x { 80 case '\'': 81 v.state = commentFilterStateContent 82 p = append(p, x) 83 case '\\': 84 v.state = commentFilterStateSingleQuoteEscape 85 default: 86 p = append(p, x) 87 } 88 case commentFilterStateSingleQuoteEscape: 89 p = append(p, '\\', x) 90 v.state = commentFilterStateSingleQuote 91 case commentFilterStateComment: 92 if x == '\n' { 93 v.state = commentFilterStateContent 94 p = append(p, '\n') 95 } 96 case commentFilterStateSlash: 97 switch x { 98 case '/': 99 v.state = commentFilterStateComment 100 case '*': 101 v.state = commentFilterStateMultilineComment 102 default: 103 p = append(p, '/', x) 104 } 105 case commentFilterStateMultilineComment: 106 switch x { 107 case '*': 108 v.state = commentFilterStateMultilineCommentStar 109 case '\n': 110 p = append(p, '\n') 111 } 112 case commentFilterStateMultilineCommentStar: 113 switch x { 114 case '/': 115 v.state = commentFilterStateContent 116 case '*': 117 // Stay 118 case '\n': 119 p = append(p, '\n') 120 default: 121 v.state = commentFilterStateMultilineComment 122 } 123 default: 124 panic("Unknown state.") 125 } 126 } 127 return len(p), nil 128 }