api.go 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. package cedar
  2. // Status reports the following statistics of the cedar:
  3. // keys: number of keys that are in the cedar,
  4. // nodes: number of trie nodes (slots in the base array) has been taken,
  5. // size: the size of the base array used by the cedar,
  6. // capacity: the capicity of the base array used by the cedar.
  7. func (da *Cedar) Status() (keys, nodes, size, capacity int) {
  8. for i := 0; i < da.Size; i++ {
  9. n := da.Array[i]
  10. if n.Check >= 0 {
  11. nodes++
  12. if n.Value >= 0 {
  13. keys++
  14. }
  15. }
  16. }
  17. return keys, nodes, da.Size, da.Capacity
  18. }
  19. // Jump travels from a node `from` to another node
  20. // `to` by following the path `path`.
  21. // For example, if the following keys were inserted:
  22. // id key
  23. // 19 abc
  24. // 23 ab
  25. // 37 abcd
  26. // then
  27. // Jump([]byte("ab"), 0) = 23, nil // reach "ab" from root
  28. // Jump([]byte("c"), 23) = 19, nil // reach "abc" from "ab"
  29. // Jump([]byte("cd"), 23) = 37, nil // reach "abcd" from "ab"
  30. func (da *Cedar) Jump(path []byte, from int) (to int, err error) {
  31. for _, b := range path {
  32. if da.Array[from].Value >= 0 {
  33. return from, ErrNoPath
  34. }
  35. to = da.Array[from].base() ^ int(b)
  36. if da.Array[to].Check != from {
  37. return from, ErrNoPath
  38. }
  39. from = to
  40. }
  41. return to, nil
  42. }
  43. // Key returns the key of the node with the given `id`.
  44. // It will return ErrNoPath, if the node does not exist.
  45. func (da *Cedar) Key(id int) (key []byte, err error) {
  46. for id > 0 {
  47. from := da.Array[id].Check
  48. if from < 0 {
  49. return nil, ErrNoPath
  50. }
  51. if char := byte(da.Array[from].base() ^ id); char != 0 {
  52. key = append(key, char)
  53. }
  54. id = from
  55. }
  56. if id != 0 || len(key) == 0 {
  57. return nil, ErrInvalidKey
  58. }
  59. for i := 0; i < len(key)/2; i++ {
  60. key[i], key[len(key)-i-1] = key[len(key)-i-1], key[i]
  61. }
  62. return key, nil
  63. }
  64. // Value returns the value of the node with the given `id`.
  65. // It will return ErrNoValue, if the node does not have a value.
  66. func (da *Cedar) Value(id int) (value int, err error) {
  67. value = da.Array[id].Value
  68. if value >= 0 {
  69. return value, nil
  70. }
  71. to := da.Array[id].base()
  72. if da.Array[to].Check == id && da.Array[to].Value >= 0 {
  73. return da.Array[to].Value, nil
  74. }
  75. return 0, ErrNoValue
  76. }
  77. // Insert adds a key-value pair into the cedar.
  78. // It will return ErrInvalidValue, if value < 0 or >= ValueLimit.
  79. func (da *Cedar) Insert(key []byte, value int) error {
  80. if value < 0 || value >= ValueLimit {
  81. return ErrInvalidValue
  82. }
  83. p := da.get(key, 0, 0)
  84. *p = value
  85. return nil
  86. }
  87. // Update increases the value associated with the `key`.
  88. // The `key` will be inserted if it is not in the cedar.
  89. // It will return ErrInvalidValue, if the updated value < 0 or >= ValueLimit.
  90. func (da *Cedar) Update(key []byte, value int) error {
  91. p := da.get(key, 0, 0)
  92. // key was not inserted
  93. if *p == ValueLimit {
  94. *p = value
  95. return nil
  96. }
  97. // key was inserted before
  98. if *p+value < 0 || *p+value >= ValueLimit {
  99. return ErrInvalidValue
  100. }
  101. *p += value
  102. return nil
  103. }
  104. // Delete removes a key-value pair from the cedar.
  105. // It will return ErrNoPath, if the key has not been added.
  106. func (da *Cedar) Delete(key []byte) error {
  107. // if the path does not exist, or the end is not a leaf,
  108. // nothing to delete
  109. to, err := da.Jump(key, 0)
  110. if err != nil {
  111. return ErrNoPath
  112. }
  113. if da.Array[to].Value < 0 {
  114. base := da.Array[to].base()
  115. if da.Array[base].Check == to {
  116. to = base
  117. }
  118. }
  119. for to > 0 {
  120. from := da.Array[to].Check
  121. base := da.Array[from].base()
  122. label := byte(to ^ base)
  123. // if `to` has sibling, remove `to` from the sibling list, then stop
  124. if da.Ninfos[to].Sibling != 0 || da.Ninfos[from].Child != label {
  125. // delete the label from the child ring first
  126. da.popSibling(from, base, label)
  127. // then release the current node `to` to the empty node ring
  128. da.pushEnode(to)
  129. break
  130. }
  131. // otherwise, just release the current node `to` to the empty node ring
  132. da.pushEnode(to)
  133. // then check its parent node
  134. to = from
  135. }
  136. return nil
  137. }
  138. // Get returns the value associated with the given `key`.
  139. // It is equivalent to
  140. // id, err1 = Jump(key)
  141. // value, err2 = Value(id)
  142. // Thus, it may return ErrNoPath or ErrNoValue,
  143. func (da *Cedar) Get(key []byte) (value int, err error) {
  144. to, err := da.Jump(key, 0)
  145. if err != nil {
  146. return 0, err
  147. }
  148. return da.Value(to)
  149. }
  150. // PrefixMatch returns a list of at most `num` nodes
  151. // which match the prefix of the key.
  152. // If `num` is 0, it returns all matches.
  153. // For example, if the following keys were inserted:
  154. // id key
  155. // 19 abc
  156. // 23 ab
  157. // 37 abcd
  158. // then
  159. // PrefixMatch([]byte("abc"), 1) = [ 23 ] // match ["ab"]
  160. // PrefixMatch([]byte("abcd"), 0) = [ 23, 19, 37]
  161. // match ["ab", "abc", "abcd"]
  162. func (da *Cedar) PrefixMatch(key []byte, num int) (ids []int) {
  163. for from, i := 0, 0; i < len(key); i++ {
  164. to, err := da.Jump(key[i:i+1], from)
  165. if err != nil {
  166. break
  167. }
  168. if _, err := da.Value(to); err == nil {
  169. ids = append(ids, to)
  170. num--
  171. if num == 0 {
  172. return
  173. }
  174. }
  175. from = to
  176. }
  177. return
  178. }
  179. // PrefixPredict returns a list of at most `num` nodes
  180. // which has the key as their prefix.
  181. // These nodes are ordered by their keys.
  182. // If `num` is 0, it returns all matches.
  183. // For example, if the following keys were inserted:
  184. // id key
  185. // 19 abc
  186. // 23 ab
  187. // 37 abcd
  188. // then
  189. // PrefixPredict([]byte("ab"), 2) = [ 23, 19 ] // predict ["ab", "abc"]
  190. // PrefixPredict([]byte("ab"), 0) = [ 23, 19, 37 ]
  191. // predict ["ab", "abc", "abcd"]
  192. func (da *Cedar) PrefixPredict(key []byte, num int) (ids []int) {
  193. root, err := da.Jump(key, 0)
  194. if err != nil {
  195. return
  196. }
  197. for from, err := da.begin(root); err == nil; from, err = da.next(from, root) {
  198. ids = append(ids, from)
  199. num--
  200. if num == 0 {
  201. return
  202. }
  203. }
  204. return
  205. }
  206. func (da *Cedar) begin(from int) (to int, err error) {
  207. for c := da.Ninfos[from].Child; c != 0; {
  208. to = da.Array[from].base() ^ int(c)
  209. c = da.Ninfos[to].Child
  210. from = to
  211. }
  212. if da.Array[from].base() > 0 {
  213. return da.Array[from].base(), nil
  214. }
  215. return from, nil
  216. }
  217. func (da *Cedar) next(from int, root int) (to int, err error) {
  218. c := da.Ninfos[from].Sibling
  219. for c == 0 && from != root && da.Array[from].Check >= 0 {
  220. from = da.Array[from].Check
  221. c = da.Ninfos[from].Sibling
  222. }
  223. if from == root {
  224. return 0, ErrNoPath
  225. }
  226. from = da.Array[da.Array[from].Check].base() ^ int(c)
  227. return da.begin(from)
  228. }