github.com/EagleQL/Xray-core@v1.4.3/infra/conf/json/reader.go (about)

     1  package json
     2  
     3  import (
     4  	"io"
     5  
     6  	"github.com/xtls/xray-core/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  }