reader.go 2.5 KB

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