You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

229 lines
5.0 KiB

  1. package substring
  2. import (
  3. "bytes"
  4. "regexp"
  5. "github.com/toqueteos/trie"
  6. )
  7. type BytesMatcher interface {
  8. Match(b []byte) bool
  9. MatchIndex(b []byte) int
  10. }
  11. // regexp
  12. type regexpBytes struct{ re *regexp.Regexp }
  13. func BytesRegexp(pat string) *regexpBytes { return &regexpBytes{regexp.MustCompile(pat)} }
  14. func (m *regexpBytes) Match(b []byte) bool { return m.re.Match(b) }
  15. func (m *regexpBytes) MatchIndex(b []byte) int {
  16. found := m.re.FindIndex(b)
  17. if found != nil {
  18. return found[1]
  19. }
  20. return -1
  21. }
  22. // exact
  23. type exactBytes struct{ pat []byte }
  24. func BytesExact(pat string) *exactBytes { return &exactBytes{[]byte(pat)} }
  25. func (m *exactBytes) Match(b []byte) bool {
  26. l, r := len(m.pat), len(b)
  27. if l != r {
  28. return false
  29. }
  30. for i := 0; i < l; i++ {
  31. if b[i] != m.pat[i] {
  32. return false
  33. }
  34. }
  35. return true
  36. }
  37. func (m *exactBytes) MatchIndex(b []byte) int {
  38. if m.Match(b) {
  39. return len(b)
  40. }
  41. return -1
  42. }
  43. // any, search `s` in `.Match(pat)`
  44. type anyBytes struct {
  45. pat []byte
  46. }
  47. func BytesAny(pat string) *anyBytes { return &anyBytes{[]byte(pat)} }
  48. func (m *anyBytes) Match(b []byte) bool { return bytes.Index(m.pat, b) >= 0 }
  49. func (m *anyBytes) MatchIndex(b []byte) int {
  50. if idx := bytes.Index(m.pat, b); idx >= 0 {
  51. return idx + len(b)
  52. }
  53. return -1
  54. }
  55. // has, search `pat` in `.Match(s)`
  56. type hasBytes struct {
  57. pat []byte
  58. }
  59. func BytesHas(pat string) *hasBytes { return &hasBytes{[]byte(pat)} }
  60. func (m *hasBytes) Match(b []byte) bool { return bytes.Index(b, m.pat) >= 0 }
  61. func (m *hasBytes) MatchIndex(b []byte) int {
  62. if idx := bytes.Index(b, m.pat); idx >= 0 {
  63. return idx + len(m.pat)
  64. }
  65. return -1
  66. }
  67. // prefix
  68. type prefixBytes struct{ pat []byte }
  69. func BytesPrefix(pat string) *prefixBytes { return &prefixBytes{[]byte(pat)} }
  70. func (m *prefixBytes) Match(b []byte) bool { return bytes.HasPrefix(b, m.pat) }
  71. func (m *prefixBytes) MatchIndex(b []byte) int {
  72. if bytes.HasPrefix(b, m.pat) {
  73. return len(m.pat)
  74. }
  75. return -1
  76. }
  77. // prefixes
  78. type prefixesBytes struct {
  79. t *trie.Trie
  80. }
  81. func BytesPrefixes(pats ...string) *prefixesBytes {
  82. t := trie.New()
  83. for _, pat := range pats {
  84. t.Insert([]byte(pat))
  85. }
  86. return &prefixesBytes{t}
  87. }
  88. func (m *prefixesBytes) Match(b []byte) bool { return m.t.PrefixIndex(b) >= 0 }
  89. func (m *prefixesBytes) MatchIndex(b []byte) int {
  90. if idx := m.t.PrefixIndex(b); idx >= 0 {
  91. return idx
  92. }
  93. return -1
  94. }
  95. // suffix
  96. type suffixBytes struct{ pat []byte }
  97. func BytesSuffix(pat string) *suffixBytes { return &suffixBytes{[]byte(pat)} }
  98. func (m *suffixBytes) Match(b []byte) bool { return bytes.HasSuffix(b, m.pat) }
  99. func (m *suffixBytes) MatchIndex(b []byte) int {
  100. if bytes.HasSuffix(b, m.pat) {
  101. return len(m.pat)
  102. }
  103. return -1
  104. }
  105. // suffixes
  106. type suffixesBytes struct {
  107. t *trie.Trie
  108. }
  109. func BytesSuffixes(pats ...string) *suffixesBytes {
  110. t := trie.New()
  111. for _, pat := range pats {
  112. t.Insert(reverse([]byte(pat)))
  113. }
  114. return &suffixesBytes{t}
  115. }
  116. func (m *suffixesBytes) Match(b []byte) bool {
  117. return m.t.PrefixIndex(reverse(b)) >= 0
  118. }
  119. func (m *suffixesBytes) MatchIndex(b []byte) int {
  120. if idx := m.t.PrefixIndex(reverse(b)); idx >= 0 {
  121. return idx
  122. }
  123. return -1
  124. }
  125. // after
  126. type afterBytes struct {
  127. first []byte
  128. matcher BytesMatcher
  129. }
  130. func BytesAfter(first string, m BytesMatcher) *afterBytes { return &afterBytes{[]byte(first), m} }
  131. func (a *afterBytes) Match(b []byte) bool {
  132. if idx := bytes.Index(b, a.first); idx >= 0 {
  133. return a.matcher.Match(b[idx+len(a.first):])
  134. }
  135. return false
  136. }
  137. func (a *afterBytes) MatchIndex(b []byte) int {
  138. if idx := bytes.Index(b, a.first); idx >= 0 {
  139. return idx + a.matcher.MatchIndex(b[idx:])
  140. }
  141. return -1
  142. }
  143. // and, returns true iff all matchers return true
  144. type andBytes struct{ matchers []BytesMatcher }
  145. func BytesAnd(m ...BytesMatcher) *andBytes { return &andBytes{m} }
  146. func (a *andBytes) Match(b []byte) bool {
  147. for _, m := range a.matchers {
  148. if !m.Match(b) {
  149. return false
  150. }
  151. }
  152. return true
  153. }
  154. func (a *andBytes) MatchIndex(b []byte) int {
  155. longest := 0
  156. for _, m := range a.matchers {
  157. if idx := m.MatchIndex(b); idx < 0 {
  158. return -1
  159. } else if idx > longest {
  160. longest = idx
  161. }
  162. }
  163. return longest
  164. }
  165. // or, returns true iff any matcher returns true
  166. type orBytes struct{ matchers []BytesMatcher }
  167. func BytesOr(m ...BytesMatcher) *orBytes { return &orBytes{m} }
  168. func (o *orBytes) Match(b []byte) bool {
  169. for _, m := range o.matchers {
  170. if m.Match(b) {
  171. return true
  172. }
  173. }
  174. return false
  175. }
  176. func (o *orBytes) MatchIndex(b []byte) int {
  177. for _, m := range o.matchers {
  178. if idx := m.MatchIndex(b); idx >= 0 {
  179. return idx
  180. }
  181. }
  182. return -1
  183. }
  184. type suffixGroupBytes struct {
  185. suffix BytesMatcher
  186. matchers []BytesMatcher
  187. }
  188. func BytesSuffixGroup(s string, m ...BytesMatcher) *suffixGroupBytes {
  189. return &suffixGroupBytes{BytesSuffix(s), m}
  190. }
  191. func (sg *suffixGroupBytes) Match(b []byte) bool {
  192. if sg.suffix.Match(b) {
  193. return BytesOr(sg.matchers...).Match(b)
  194. }
  195. return false
  196. }
  197. func (sg *suffixGroupBytes) MatchIndex(b []byte) int {
  198. if sg.suffix.MatchIndex(b) >= 0 {
  199. return BytesOr(sg.matchers...).MatchIndex(b)
  200. }
  201. return -1
  202. }