reader.go 2.8 KB

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