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.

85 lines
2.2 KiB

  1. // Copyright (c) 2017 Couchbase, Inc.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package vellum
  15. // Automaton represents the general contract of a byte-based finite automaton
  16. type Automaton interface {
  17. // Start returns the start state
  18. Start() int
  19. // IsMatch returns true if and only if the state is a match
  20. IsMatch(int) bool
  21. // CanMatch returns true if and only if it is possible to reach a match
  22. // in zero or more steps
  23. CanMatch(int) bool
  24. // WillAlwaysMatch returns true if and only if the current state matches
  25. // and will always match no matter what steps are taken
  26. WillAlwaysMatch(int) bool
  27. // Accept returns the next state given the input to the specified state
  28. Accept(int, byte) int
  29. }
  30. // AutomatonContains implements an generic Contains() method which works
  31. // on any implementation of Automaton
  32. func AutomatonContains(a Automaton, k []byte) bool {
  33. i := 0
  34. curr := a.Start()
  35. for a.CanMatch(curr) && i < len(k) {
  36. curr = a.Accept(curr, k[i])
  37. if curr == noneAddr {
  38. break
  39. }
  40. i++
  41. }
  42. if i != len(k) {
  43. return false
  44. }
  45. return a.IsMatch(curr)
  46. }
  47. // AlwaysMatch is an Automaton implementation which always matches
  48. type AlwaysMatch struct{}
  49. // Start returns the AlwaysMatch start state
  50. func (m *AlwaysMatch) Start() int {
  51. return 0
  52. }
  53. // IsMatch always returns true
  54. func (m *AlwaysMatch) IsMatch(int) bool {
  55. return true
  56. }
  57. // CanMatch always returns true
  58. func (m *AlwaysMatch) CanMatch(int) bool {
  59. return true
  60. }
  61. // WillAlwaysMatch always returns true
  62. func (m *AlwaysMatch) WillAlwaysMatch(int) bool {
  63. return true
  64. }
  65. // Accept returns the next AlwaysMatch state
  66. func (m *AlwaysMatch) Accept(int, byte) int {
  67. return 0
  68. }
  69. // creating an alwaysMatchAutomaton to avoid unnecesary repeated allocations.
  70. var alwaysMatchAutomaton = &AlwaysMatch{}