github.com/xmplusdev/xmcore@v1.8.11-0.20240412132628-5518b55526af/infra/conf/json/reader.go (about) 1 package json 2 3 import ( 4 "io" 5 6 "github.com/xmplusdev/xmcore/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 br *buf.BufferedReader 32 } 33 34 // Read implements io.Reader.Read(). Buffer must be at least 3 bytes. 35 func (v *Reader) Read(b []byte) (int, error) { 36 if v.br == nil { 37 v.br = &buf.BufferedReader{Reader: buf.NewReader(v.Reader)} 38 } 39 40 p := b[:0] 41 for len(p) < len(b)-2 { 42 x, err := v.br.ReadByte() 43 if err != nil { 44 if len(p) == 0 { 45 return 0, err 46 } 47 return len(p), nil 48 } 49 switch v.state { 50 case StateContent: 51 switch x { 52 case '"': 53 v.state = StateDoubleQuote 54 p = append(p, x) 55 case '\'': 56 v.state = StateSingleQuote 57 p = append(p, x) 58 case '\\': 59 v.state = StateEscape 60 case '#': 61 v.state = StateComment 62 case '/': 63 v.state = StateSlash 64 default: 65 p = append(p, x) 66 } 67 case StateEscape: 68 p = append(p, '\\', x) 69 v.state = StateContent 70 case StateDoubleQuote: 71 switch x { 72 case '"': 73 v.state = StateContent 74 p = append(p, x) 75 case '\\': 76 v.state = StateDoubleQuoteEscape 77 default: 78 p = append(p, x) 79 } 80 case StateDoubleQuoteEscape: 81 p = append(p, '\\', x) 82 v.state = StateDoubleQuote 83 case StateSingleQuote: 84 switch x { 85 case '\'': 86 v.state = StateContent 87 p = append(p, x) 88 case '\\': 89 v.state = StateSingleQuoteEscape 90 default: 91 p = append(p, x) 92 } 93 case StateSingleQuoteEscape: 94 p = append(p, '\\', x) 95 v.state = StateSingleQuote 96 case StateComment: 97 if x == '\n' { 98 v.state = StateContent 99 p = append(p, '\n') 100 } 101 case StateSlash: 102 switch x { 103 case '/': 104 v.state = StateComment 105 case '*': 106 v.state = StateMultilineComment 107 default: 108 p = append(p, '/', x) 109 } 110 case StateMultilineComment: 111 switch x { 112 case '*': 113 v.state = StateMultilineCommentStar 114 case '\n': 115 p = append(p, '\n') 116 } 117 case StateMultilineCommentStar: 118 switch x { 119 case '/': 120 v.state = StateContent 121 case '*': 122 // Stay 123 case '\n': 124 p = append(p, '\n') 125 default: 126 v.state = StateMultilineComment 127 } 128 default: 129 panic("Unknown state.") 130 } 131 } 132 return len(p), nil 133 }