github.com/sunvim/utils@v0.1.0/patricia/patricia.go (about) 1 // Copyright (c) 2014 The go-patricia AUTHORS 2 // 3 // Use of this source code is governed by The MIT License 4 // that can be found in the LICENSE file. 5 6 package patricia 7 8 import ( 9 "bytes" 10 "errors" 11 "fmt" 12 "io" 13 "strings" 14 ) 15 16 //------------------------------------------------------------------------------ 17 // Trie 18 //------------------------------------------------------------------------------ 19 20 const ( 21 DefaultMaxPrefixPerNode = 10 22 DefaultMaxChildrenPerSparseNode = 8 23 ) 24 25 type ( 26 Prefix []byte 27 Item interface{} 28 VisitorFunc func(prefix Prefix, item Item) error 29 ) 30 31 // Trie is a generic patricia trie that allows fast retrieval of items by prefix. 32 // and other funky stuff. 33 // 34 // Trie is not thread-safe. 35 type Trie struct { 36 prefix Prefix 37 item Item 38 39 maxPrefixPerNode int 40 maxChildrenPerSparseNode int 41 42 children childList 43 } 44 45 // Public API ------------------------------------------------------------------ 46 47 type Option func(*Trie) 48 49 // Trie constructor. 50 func NewTrie(options ...Option) *Trie { 51 trie := &Trie{} 52 53 for _, opt := range options { 54 opt(trie) 55 } 56 57 if trie.maxPrefixPerNode <= 0 { 58 trie.maxPrefixPerNode = DefaultMaxPrefixPerNode 59 } 60 if trie.maxChildrenPerSparseNode <= 0 { 61 trie.maxChildrenPerSparseNode = DefaultMaxChildrenPerSparseNode 62 } 63 64 trie.children = newSparseChildList(trie.maxChildrenPerSparseNode) 65 return trie 66 } 67 68 func MaxPrefixPerNode(value int) Option { 69 return func(trie *Trie) { 70 trie.maxPrefixPerNode = value 71 } 72 } 73 74 func MaxChildrenPerSparseNode(value int) Option { 75 return func(trie *Trie) { 76 trie.maxChildrenPerSparseNode = value 77 } 78 } 79 80 // Clone makes a copy of an existing trie. 81 // Items stored in both tries become shared, obviously. 82 func (trie *Trie) Clone() *Trie { 83 return &Trie{ 84 prefix: append(Prefix(nil), trie.prefix...), 85 item: trie.item, 86 maxPrefixPerNode: trie.maxPrefixPerNode, 87 maxChildrenPerSparseNode: trie.maxChildrenPerSparseNode, 88 children: trie.children.clone(), 89 } 90 } 91 92 // Item returns the item stored in the root of this trie. 93 func (trie *Trie) Item() Item { 94 return trie.item 95 } 96 97 // Insert inserts a new item into the trie using the given prefix. Insert does 98 // not replace existing items. It returns false if an item was already in place. 99 func (trie *Trie) Insert(key Prefix, item Item) (inserted bool) { 100 return trie.put(key, item, false) 101 } 102 103 // Set works much like Insert, but it always sets the item, possibly replacing 104 // the item previously inserted. 105 func (trie *Trie) Set(key Prefix, item Item) { 106 trie.put(key, item, true) 107 } 108 109 // Get returns the item located at key. 110 // 111 // This method is a bit dangerous, because Get can as well end up in an internal 112 // node that is not really representing any user-defined value. So when nil is 113 // a valid value being used, it is not possible to tell if the value was inserted 114 // into the tree by the user or not. A possible workaround for this is not to use 115 // nil interface as a valid value, even using zero value of any type is enough 116 // to prevent this bad behaviour. 117 func (trie *Trie) Get(key Prefix) (item Item) { 118 _, node, found, leftover := trie.findSubtree(key) 119 if !found || len(leftover) != 0 { 120 return nil 121 } 122 return node.item 123 } 124 125 // Match returns what Get(prefix) != nil would return. The same warning as for 126 // Get applies here as well. 127 func (trie *Trie) Match(prefix Prefix) (matchedExactly bool) { 128 return trie.Get(prefix) != nil 129 } 130 131 // MatchSubtree returns true when there is a subtree representing extensions 132 // to key, that is if there are any keys in the tree which have key as prefix. 133 func (trie *Trie) MatchSubtree(key Prefix) (matched bool) { 134 _, _, matched, _ = trie.findSubtree(key) 135 return 136 } 137 138 // Visit calls visitor on every node containing a non-nil item 139 // in alphabetical order. 140 // 141 // If an error is returned from visitor, the function stops visiting the tree 142 // and returns that error, unless it is a special error - SkipSubtree. In that 143 // case Visit skips the subtree represented by the current node and continues 144 // elsewhere. 145 func (trie *Trie) Visit(visitor VisitorFunc) error { 146 return trie.walk(nil, visitor) 147 } 148 149 func (trie *Trie) size() int { 150 n := 0 151 152 trie.walk(nil, func(prefix Prefix, item Item) error { 153 n++ 154 return nil 155 }) 156 157 return n 158 } 159 160 func (trie *Trie) total() int { 161 return 1 + trie.children.total() 162 } 163 164 // VisitSubtree works much like Visit, but it only visits nodes matching prefix. 165 func (trie *Trie) VisitSubtree(prefix Prefix, visitor VisitorFunc) error { 166 // Nil prefix not allowed. 167 if prefix == nil { 168 panic(ErrNilPrefix) 169 } 170 171 // Empty trie must be handled explicitly. 172 if trie.prefix == nil { 173 return nil 174 } 175 176 // Locate the relevant subtree. 177 _, root, found, leftover := trie.findSubtree(prefix) 178 if !found { 179 return nil 180 } 181 prefix = append(prefix, leftover...) 182 183 // Visit it. 184 return root.walk(prefix, visitor) 185 } 186 187 // VisitPrefixes visits only nodes that represent prefixes of key. 188 // To say the obvious, returning SkipSubtree from visitor makes no sense here. 189 func (trie *Trie) VisitPrefixes(key Prefix, visitor VisitorFunc) error { 190 // Nil key not allowed. 191 if key == nil { 192 panic(ErrNilPrefix) 193 } 194 195 // Empty trie must be handled explicitly. 196 if trie.prefix == nil { 197 return nil 198 } 199 200 // Walk the path matching key prefixes. 201 node := trie 202 prefix := key 203 offset := 0 204 for { 205 // Compute what part of prefix matches. 206 common := node.longestCommonPrefixLength(key) 207 key = key[common:] 208 offset += common 209 210 // Partial match means that there is no subtree matching prefix. 211 if common < len(node.prefix) { 212 return nil 213 } 214 215 // Call the visitor. 216 if item := node.item; item != nil { 217 if err := visitor(prefix[:offset], item); err != nil { 218 return err 219 } 220 } 221 222 if len(key) == 0 { 223 // This node represents key, we are finished. 224 return nil 225 } 226 227 // There is some key suffix left, move to the children. 228 child := node.children.next(key[0]) 229 if child == nil { 230 // There is nowhere to continue, return. 231 return nil 232 } 233 234 node = child 235 } 236 } 237 238 // Delete deletes the item represented by the given prefix. 239 // 240 // True is returned if the matching node was found and deleted. 241 func (trie *Trie) Delete(key Prefix) (deleted bool) { 242 // Nil prefix not allowed. 243 if key == nil { 244 panic(ErrNilPrefix) 245 } 246 247 // Empty trie must be handled explicitly. 248 if trie.prefix == nil { 249 return false 250 } 251 252 // Find the relevant node. 253 path, found, _ := trie.findSubtreePath(key) 254 if !found { 255 return false 256 } 257 258 node := path[len(path)-1] 259 var parent *Trie 260 if len(path) != 1 { 261 parent = path[len(path)-2] 262 } 263 264 // If the item is already set to nil, there is nothing to do. 265 if node.item == nil { 266 return false 267 } 268 269 // Delete the item. 270 node.item = nil 271 272 // Initialise i before goto. 273 // Will be used later in a loop. 274 i := len(path) - 1 275 276 // In case there are some child nodes, we cannot drop the whole subtree. 277 // We can try to compact nodes, though. 278 if node.children.length() != 0 { 279 goto Compact 280 } 281 282 // In case we are at the root, just reset it and we are done. 283 if parent == nil { 284 node.reset() 285 return true 286 } 287 288 // We can drop a subtree. 289 // Find the first ancestor that has its value set or it has 2 or more child nodes. 290 // That will be the node where to drop the subtree at. 291 for ; i >= 0; i-- { 292 if current := path[i]; current.item != nil || current.children.length() >= 2 { 293 break 294 } 295 } 296 297 // Handle the case when there is no such node. 298 // In other words, we can reset the whole tree. 299 if i == -1 { 300 path[0].reset() 301 return true 302 } 303 304 // We can just remove the subtree here. 305 node = path[i] 306 if i == 0 { 307 parent = nil 308 } else { 309 parent = path[i-1] 310 } 311 // i+1 is always a valid index since i is never pointing to the last node. 312 // The loop above skips at least the last node since we are sure that the item 313 // is set to nil and it has no children, othewise we would be compacting instead. 314 node.children.remove(path[i+1].prefix[0]) 315 316 Compact: 317 // The node is set to the first non-empty ancestor, 318 // so try to compact since that might be possible now. 319 if compacted := node.compact(); compacted != node { 320 if parent == nil { 321 *node = *compacted 322 } else { 323 parent.children.replace(node.prefix[0], compacted) 324 *parent = *parent.compact() 325 } 326 } 327 328 return true 329 } 330 331 // DeleteSubtree finds the subtree exactly matching prefix and deletes it. 332 // 333 // True is returned if the subtree was found and deleted. 334 func (trie *Trie) DeleteSubtree(prefix Prefix) (deleted bool) { 335 // Nil prefix not allowed. 336 if prefix == nil { 337 panic(ErrNilPrefix) 338 } 339 340 // Empty trie must be handled explicitly. 341 if trie.prefix == nil { 342 return false 343 } 344 345 // Locate the relevant subtree. 346 parent, root, found, _ := trie.findSubtree(prefix) 347 if !found { 348 return false 349 } 350 351 // If we are in the root of the trie, reset the trie. 352 if parent == nil { 353 root.reset() 354 return true 355 } 356 357 // Otherwise remove the root node from its parent. 358 parent.children.remove(root.prefix[0]) 359 return true 360 } 361 362 // Internal helper methods ----------------------------------------------------- 363 364 func (trie *Trie) empty() bool { 365 return trie.item == nil && trie.children.length() == 0 366 } 367 368 func (trie *Trie) reset() { 369 trie.prefix = nil 370 trie.children = newSparseChildList(trie.maxPrefixPerNode) 371 } 372 373 func (trie *Trie) put(key Prefix, item Item, replace bool) (inserted bool) { 374 // Nil prefix not allowed. 375 if key == nil { 376 panic(ErrNilPrefix) 377 } 378 379 var ( 380 common int 381 node *Trie = trie 382 child *Trie 383 ) 384 385 if node.prefix == nil { 386 if len(key) <= trie.maxPrefixPerNode { 387 node.prefix = key 388 goto InsertItem 389 } 390 node.prefix = key[:trie.maxPrefixPerNode] 391 key = key[trie.maxPrefixPerNode:] 392 goto AppendChild 393 } 394 395 for { 396 // Compute the longest common prefix length. 397 common = node.longestCommonPrefixLength(key) 398 key = key[common:] 399 400 // Only a part matches, split. 401 if common < len(node.prefix) { 402 goto SplitPrefix 403 } 404 405 // common == len(node.prefix) since never (common > len(node.prefix)) 406 // common == len(former key) <-> 0 == len(key) 407 // -> former key == node.prefix 408 if len(key) == 0 { 409 goto InsertItem 410 } 411 412 // Check children for matching prefix. 413 child = node.children.next(key[0]) 414 if child == nil { 415 goto AppendChild 416 } 417 node = child 418 } 419 420 SplitPrefix: 421 // Split the prefix if necessary. 422 child = new(Trie) 423 *child = *node 424 *node = *NewTrie() 425 node.prefix = child.prefix[:common] 426 child.prefix = child.prefix[common:] 427 child = child.compact() 428 node.children = node.children.add(child) 429 430 AppendChild: 431 // Keep appending children until whole prefix is inserted. 432 // This loop starts with empty node.prefix that needs to be filled. 433 for len(key) != 0 { 434 child := NewTrie() 435 if len(key) <= trie.maxPrefixPerNode { 436 child.prefix = key 437 node.children = node.children.add(child) 438 node = child 439 goto InsertItem 440 } else { 441 child.prefix = key[:trie.maxPrefixPerNode] 442 key = key[trie.maxPrefixPerNode:] 443 node.children = node.children.add(child) 444 node = child 445 } 446 } 447 448 InsertItem: 449 // Try to insert the item if possible. 450 if replace || node.item == nil { 451 node.item = item 452 return true 453 } 454 return false 455 } 456 457 func (trie *Trie) compact() *Trie { 458 // Only a node with a single child can be compacted. 459 if trie.children.length() != 1 { 460 return trie 461 } 462 463 child := trie.children.head() 464 465 // If any item is set, we cannot compact since we want to retain 466 // the ability to do searching by key. This makes compaction less usable, 467 // but that simply cannot be avoided. 468 if trie.item != nil || child.item != nil { 469 return trie 470 } 471 472 // Make sure the combined prefixes fit into a single node. 473 if len(trie.prefix)+len(child.prefix) > trie.maxPrefixPerNode { 474 return trie 475 } 476 477 // Concatenate the prefixes, move the items. 478 child.prefix = append(trie.prefix, child.prefix...) 479 if trie.item != nil { 480 child.item = trie.item 481 } 482 483 return child 484 } 485 486 func (trie *Trie) findSubtree(prefix Prefix) (parent *Trie, root *Trie, found bool, leftover Prefix) { 487 // Find the subtree matching prefix. 488 root = trie 489 for { 490 // Compute what part of prefix matches. 491 common := root.longestCommonPrefixLength(prefix) 492 prefix = prefix[common:] 493 494 // We used up the whole prefix, subtree found. 495 if len(prefix) == 0 { 496 found = true 497 leftover = root.prefix[common:] 498 return 499 } 500 501 // Partial match means that there is no subtree matching prefix. 502 if common < len(root.prefix) { 503 leftover = root.prefix[common:] 504 return 505 } 506 507 // There is some prefix left, move to the children. 508 child := root.children.next(prefix[0]) 509 if child == nil { 510 // There is nowhere to continue, there is no subtree matching prefix. 511 return 512 } 513 514 parent = root 515 root = child 516 } 517 } 518 519 func (trie *Trie) findSubtreePath(prefix Prefix) (path []*Trie, found bool, leftover Prefix) { 520 // Find the subtree matching prefix. 521 root := trie 522 var subtreePath []*Trie 523 for { 524 // Append the current root to the path. 525 subtreePath = append(subtreePath, root) 526 527 // Compute what part of prefix matches. 528 common := root.longestCommonPrefixLength(prefix) 529 prefix = prefix[common:] 530 531 // We used up the whole prefix, subtree found. 532 if len(prefix) == 0 { 533 path = subtreePath 534 found = true 535 leftover = root.prefix[common:] 536 return 537 } 538 539 // Partial match means that there is no subtree matching prefix. 540 if common < len(root.prefix) { 541 leftover = root.prefix[common:] 542 return 543 } 544 545 // There is some prefix left, move to the children. 546 child := root.children.next(prefix[0]) 547 if child == nil { 548 // There is nowhere to continue, there is no subtree matching prefix. 549 return 550 } 551 552 root = child 553 } 554 } 555 556 func (trie *Trie) walk(actualRootPrefix Prefix, visitor VisitorFunc) error { 557 var prefix Prefix 558 // Allocate a bit more space for prefix at the beginning. 559 if actualRootPrefix == nil { 560 prefix = make(Prefix, 32+len(trie.prefix)) 561 copy(prefix, trie.prefix) 562 prefix = prefix[:len(trie.prefix)] 563 } else { 564 prefix = make(Prefix, 32+len(actualRootPrefix)) 565 copy(prefix, actualRootPrefix) 566 prefix = prefix[:len(actualRootPrefix)] 567 } 568 569 // Visit the root first. Not that this works for empty trie as well since 570 // in that case item == nil && len(children) == 0. 571 if trie.item != nil { 572 if err := visitor(prefix, trie.item); err != nil { 573 if err == SkipSubtree { 574 return nil 575 } 576 return err 577 } 578 } 579 580 // Then continue to the children. 581 return trie.children.walk(&prefix, visitor) 582 } 583 584 func (trie *Trie) longestCommonPrefixLength(prefix Prefix) (i int) { 585 for ; i < len(prefix) && i < len(trie.prefix) && prefix[i] == trie.prefix[i]; i++ { 586 } 587 return 588 } 589 590 func (trie *Trie) dump() string { 591 writer := &bytes.Buffer{} 592 trie.print(writer, 0) 593 return writer.String() 594 } 595 596 func (trie *Trie) print(writer io.Writer, indent int) { 597 fmt.Fprintf(writer, "%s%s %v\n", strings.Repeat(" ", indent), string(trie.prefix), trie.item) 598 trie.children.print(writer, indent+2) 599 } 600 601 // Errors ---------------------------------------------------------------------- 602 603 var ( 604 SkipSubtree = errors.New("Skip this subtree") 605 ErrNilPrefix = errors.New("Nil prefix passed into a method call") 606 )