btree.go 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. package match
  2. import (
  3. "fmt"
  4. "unicode/utf8"
  5. )
  6. type BTree struct {
  7. Value Matcher
  8. Left Matcher
  9. Right Matcher
  10. ValueLengthRunes int
  11. LeftLengthRunes int
  12. RightLengthRunes int
  13. LengthRunes int
  14. }
  15. func NewBTree(Value, Left, Right Matcher) (tree BTree) {
  16. tree.Value = Value
  17. tree.Left = Left
  18. tree.Right = Right
  19. lenOk := true
  20. if tree.ValueLengthRunes = Value.Len(); tree.ValueLengthRunes == -1 {
  21. lenOk = false
  22. }
  23. if Left != nil {
  24. if tree.LeftLengthRunes = Left.Len(); tree.LeftLengthRunes == -1 {
  25. lenOk = false
  26. }
  27. }
  28. if Right != nil {
  29. if tree.RightLengthRunes = Right.Len(); tree.RightLengthRunes == -1 {
  30. lenOk = false
  31. }
  32. }
  33. if lenOk {
  34. tree.LengthRunes = tree.LeftLengthRunes + tree.ValueLengthRunes + tree.RightLengthRunes
  35. } else {
  36. tree.LengthRunes = -1
  37. }
  38. return tree
  39. }
  40. func (self BTree) Len() int {
  41. return self.LengthRunes
  42. }
  43. // todo?
  44. func (self BTree) Index(s string) (index int, segments []int) {
  45. //inputLen := len(s)
  46. //// try to cut unnecessary parts
  47. //// by knowledge of length of right and left part
  48. //offset, limit := self.offsetLimit(inputLen)
  49. //for offset < limit {
  50. // // search for matching part in substring
  51. // vi, segments := self.Value.Index(s[offset:limit])
  52. // if index == -1 {
  53. // return -1, nil
  54. // }
  55. // if self.Left == nil {
  56. // if index != offset {
  57. // return -1, nil
  58. // }
  59. // } else {
  60. // left := s[:offset+vi]
  61. // i := self.Left.IndexSuffix(left)
  62. // if i == -1 {
  63. // return -1, nil
  64. // }
  65. // index = i
  66. // }
  67. // if self.Right != nil {
  68. // for _, seg := range segments {
  69. // right := s[:offset+vi+seg]
  70. // }
  71. // }
  72. // l := s[:offset+index]
  73. // var left bool
  74. // if self.Left != nil {
  75. // left = self.Left.Index(l)
  76. // } else {
  77. // left = l == ""
  78. // }
  79. //}
  80. return -1, nil
  81. }
  82. func (self BTree) Match(s string) bool {
  83. inputLen := len(s)
  84. // try to cut unnecessary parts
  85. // by knowledge of length of right and left part
  86. offset, limit := self.offsetLimit(inputLen)
  87. for offset < limit {
  88. // search for matching part in substring
  89. index, segments := self.Value.Index(s[offset:limit])
  90. if index == -1 {
  91. releaseSegments(segments)
  92. return false
  93. }
  94. l := s[:offset+index]
  95. var left bool
  96. if self.Left != nil {
  97. left = self.Left.Match(l)
  98. } else {
  99. left = l == ""
  100. }
  101. if left {
  102. for i := len(segments) - 1; i >= 0; i-- {
  103. length := segments[i]
  104. var right bool
  105. var r string
  106. // if there is no string for the right branch
  107. if inputLen <= offset+index+length {
  108. r = ""
  109. } else {
  110. r = s[offset+index+length:]
  111. }
  112. if self.Right != nil {
  113. right = self.Right.Match(r)
  114. } else {
  115. right = r == ""
  116. }
  117. if right {
  118. releaseSegments(segments)
  119. return true
  120. }
  121. }
  122. }
  123. _, step := utf8.DecodeRuneInString(s[offset+index:])
  124. offset += index + step
  125. releaseSegments(segments)
  126. }
  127. return false
  128. }
  129. func (self BTree) offsetLimit(inputLen int) (offset int, limit int) {
  130. // self.Length, self.RLen and self.LLen are values meaning the length of runes for each part
  131. // here we manipulating byte length for better optimizations
  132. // but these checks still works, cause minLen of 1-rune string is 1 byte.
  133. if self.LengthRunes != -1 && self.LengthRunes > inputLen {
  134. return 0, 0
  135. }
  136. if self.LeftLengthRunes >= 0 {
  137. offset = self.LeftLengthRunes
  138. }
  139. if self.RightLengthRunes >= 0 {
  140. limit = inputLen - self.RightLengthRunes
  141. } else {
  142. limit = inputLen
  143. }
  144. return offset, limit
  145. }
  146. func (self BTree) String() string {
  147. const n string = "<nil>"
  148. var l, r string
  149. if self.Left == nil {
  150. l = n
  151. } else {
  152. l = self.Left.String()
  153. }
  154. if self.Right == nil {
  155. r = n
  156. } else {
  157. r = self.Right.String()
  158. }
  159. return fmt.Sprintf("<btree:[%s<-%s->%s]>", l, self.Value, r)
  160. }