github.com/imannamdari/v2ray-core/v5@v5.0.5/infra/conf/json/reader.go (about) 1 package json 2 3 import ( 4 "io" 5 6 "github.com/imannamdari/v2ray-core/v5/common/buf" 7 ) 8 9 // State is the internal state of parser. 10 type State byte 11 12 const ( 13 StateContent State = iota 14 StateEscape 15 StateDoubleQuote 16 StateDoubleQuoteEscape 17 StateSingleQuote 18 StateSingleQuoteEscape 19 StateComment 20 StateSlash 21 StateMultilineComment 22 StateMultilineCommentStar 23 ) 24 25 // Reader is a reader for filtering comments. 26 // It supports Java style single and multi line comment syntax, and Python style single line comment syntax. 27 type Reader struct { 28 io.Reader 29 30 state State 31 pending []byte 32 br *buf.BufferedReader 33 } 34 35 // Read implements io.Reader.Read(). 36 func (v *Reader) Read(b []byte) (int, error) { 37 if v.br == nil { 38 v.br = &buf.BufferedReader{Reader: buf.NewReader(v.Reader)} 39 } 40 41 p := b[:0] 42 for len(p) < len(b) { 43 if len(v.pending) > 0 { 44 max := len(b) - len(p) 45 if max > len(v.pending) { 46 max = len(v.pending) 47 } 48 p = append(p, v.pending[:max]...) 49 v.pending = v.pending[max:] 50 continue 51 } 52 53 x, err := v.br.ReadByte() 54 if err != nil { 55 if len(p) == 0 { 56 return 0, err 57 } 58 return len(p), nil 59 } 60 switch v.state { 61 case StateContent: 62 switch x { 63 case '"': 64 v.state = StateDoubleQuote 65 p = append(p, x) 66 case '\'': 67 v.state = StateSingleQuote 68 p = append(p, x) 69 case '\\': 70 v.state = StateEscape 71 p = append(p, x) 72 case '#': 73 v.state = StateComment 74 case '/': 75 v.state = StateSlash 76 default: 77 p = append(p, x) 78 } 79 case StateEscape: 80 p = append(p, x) 81 v.state = StateContent 82 case StateDoubleQuote: 83 switch x { 84 case '"': 85 v.state = StateContent 86 p = append(p, x) 87 case '\\': 88 v.state = StateDoubleQuoteEscape 89 p = append(p, x) 90 default: 91 p = append(p, x) 92 } 93 case StateDoubleQuoteEscape: 94 p = append(p, x) 95 v.state = StateDoubleQuote 96 case StateSingleQuote: 97 switch x { 98 case '\'': 99 v.state = StateContent 100 p = append(p, x) 101 case '\\': 102 v.state = StateSingleQuoteEscape 103 p = append(p, x) 104 default: 105 p = append(p, x) 106 } 107 case StateSingleQuoteEscape: 108 p = append(p, x) 109 v.state = StateSingleQuote 110 case StateComment: 111 if x == '\n' { 112 v.state = StateContent 113 p = append(p, x) 114 } 115 case StateSlash: 116 switch x { 117 case '/': 118 v.state = StateComment 119 case '*': 120 v.state = StateMultilineComment 121 default: 122 v.state = StateContent 123 v.pending = append(v.pending, x) 124 p = append(p, '/') 125 } 126 case StateMultilineComment: 127 switch x { 128 case '*': 129 v.state = StateMultilineCommentStar 130 case '\n': 131 p = append(p, x) 132 } 133 case StateMultilineCommentStar: 134 switch x { 135 case '/': 136 v.state = StateContent 137 case '*': 138 // Stay 139 case '\n': 140 p = append(p, x) 141 default: 142 v.state = StateMultilineComment 143 } 144 default: 145 panic("Unknown state.") 146 } 147 } 148 return len(p), nil 149 }