comment.go 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. package json
  2. import (
  3. "bufio"
  4. "io"
  5. )
  6. // kanged from v2ray
  7. type commentFilterState = byte
  8. const (
  9. commentFilterStateContent commentFilterState = iota
  10. commentFilterStateEscape
  11. commentFilterStateDoubleQuote
  12. commentFilterStateDoubleQuoteEscape
  13. commentFilterStateSingleQuote
  14. commentFilterStateSingleQuoteEscape
  15. commentFilterStateComment
  16. commentFilterStateSlash
  17. commentFilterStateMultilineComment
  18. commentFilterStateMultilineCommentStar
  19. )
  20. type CommentFilter struct {
  21. br *bufio.Reader
  22. state commentFilterState
  23. }
  24. func NewCommentFilter(reader io.Reader) io.Reader {
  25. return &CommentFilter{br: bufio.NewReader(reader)}
  26. }
  27. func (v *CommentFilter) Read(b []byte) (int, error) {
  28. p := b[:0]
  29. for len(p) < len(b)-2 {
  30. x, err := v.br.ReadByte()
  31. if err != nil {
  32. if len(p) == 0 {
  33. return 0, err
  34. }
  35. return len(p), nil
  36. }
  37. switch v.state {
  38. case commentFilterStateContent:
  39. switch x {
  40. case '"':
  41. v.state = commentFilterStateDoubleQuote
  42. p = append(p, x)
  43. case '\'':
  44. v.state = commentFilterStateSingleQuote
  45. p = append(p, x)
  46. case '\\':
  47. v.state = commentFilterStateEscape
  48. case '#':
  49. v.state = commentFilterStateComment
  50. case '/':
  51. v.state = commentFilterStateSlash
  52. default:
  53. p = append(p, x)
  54. }
  55. case commentFilterStateEscape:
  56. p = append(p, '\\', x)
  57. v.state = commentFilterStateContent
  58. case commentFilterStateDoubleQuote:
  59. switch x {
  60. case '"':
  61. v.state = commentFilterStateContent
  62. p = append(p, x)
  63. case '\\':
  64. v.state = commentFilterStateDoubleQuoteEscape
  65. default:
  66. p = append(p, x)
  67. }
  68. case commentFilterStateDoubleQuoteEscape:
  69. p = append(p, '\\', x)
  70. v.state = commentFilterStateDoubleQuote
  71. case commentFilterStateSingleQuote:
  72. switch x {
  73. case '\'':
  74. v.state = commentFilterStateContent
  75. p = append(p, x)
  76. case '\\':
  77. v.state = commentFilterStateSingleQuoteEscape
  78. default:
  79. p = append(p, x)
  80. }
  81. case commentFilterStateSingleQuoteEscape:
  82. p = append(p, '\\', x)
  83. v.state = commentFilterStateSingleQuote
  84. case commentFilterStateComment:
  85. if x == '\n' {
  86. v.state = commentFilterStateContent
  87. p = append(p, '\n')
  88. }
  89. case commentFilterStateSlash:
  90. switch x {
  91. case '/':
  92. v.state = commentFilterStateComment
  93. case '*':
  94. v.state = commentFilterStateMultilineComment
  95. default:
  96. p = append(p, '/', x)
  97. }
  98. case commentFilterStateMultilineComment:
  99. switch x {
  100. case '*':
  101. v.state = commentFilterStateMultilineCommentStar
  102. case '\n':
  103. p = append(p, '\n')
  104. }
  105. case commentFilterStateMultilineCommentStar:
  106. switch x {
  107. case '/':
  108. v.state = commentFilterStateContent
  109. case '*':
  110. // Stay
  111. case '\n':
  112. p = append(p, '\n')
  113. default:
  114. v.state = commentFilterStateMultilineComment
  115. }
  116. default:
  117. panic("Unknown state.")
  118. }
  119. }
  120. return len(p), nil
  121. }