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  )