package json import ( "io" ) // State is the internal state of parser. type State byte const ( StateContent State = iota StateEscape StateDoubleQuote StateDoubleQuoteEscape StateSingleQuote StateSingleQuoteEscape StateComment StateSlash StateMultilineComment StateMultilineCommentStar ) // Reader is a JSON reader which allows comments. type Reader struct { io.Reader state State } // Read implements io.Reader.Read(). func (v *Reader) Read(b []byte) (int, error) { n, err := v.Reader.Read(b) if err != nil { return n, err } p := b[:0] for _, x := range b[:n] { switch v.state { case StateContent: switch x { case '"': v.state = StateDoubleQuote p = append(p, x) case '\'': v.state = StateSingleQuote p = append(p, x) case '\\': v.state = StateEscape case '#': v.state = StateComment case '/': v.state = StateSlash default: p = append(p, x) } case StateEscape: p = append(p, '\\', x) v.state = StateContent case StateDoubleQuote: switch x { case '"': v.state = StateContent p = append(p, x) case '\\': v.state = StateDoubleQuoteEscape default: p = append(p, x) } case StateDoubleQuoteEscape: p = append(p, '\\', x) v.state = StateDoubleQuote case StateSingleQuote: switch x { case '\'': v.state = StateContent p = append(p, x) case '\\': v.state = StateSingleQuoteEscape default: p = append(p, x) } case StateSingleQuoteEscape: p = append(p, '\\', x) v.state = StateSingleQuote case StateComment: if x == '\n' { v.state = StateContent } case StateSlash: switch x { case '/': v.state = StateComment case '*': v.state = StateMultilineComment default: p = append(p, '/', x) } case StateMultilineComment: if x == '*' { v.state = StateMultilineCommentStar } case StateMultilineCommentStar: switch x { case '/': v.state = StateContent case '*': // Stay default: v.state = StateMultilineComment } default: panic("Unknown state.") } } return len(p), nil }