github.com/sunvim/utils@v0.1.0/patricia/children.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  	"fmt"
    10  	"io"
    11  	"sort"
    12  )
    13  
    14  type childList interface {
    15  	length() int
    16  	head() *Trie
    17  	add(child *Trie) childList
    18  	remove(b byte)
    19  	replace(b byte, child *Trie)
    20  	next(b byte) *Trie
    21  	walk(prefix *Prefix, visitor VisitorFunc) error
    22  	print(w io.Writer, indent int)
    23  	clone() childList
    24  	total() int
    25  }
    26  
    27  type tries []*Trie
    28  
    29  func (t tries) Len() int {
    30  	return len(t)
    31  }
    32  
    33  func (t tries) Less(i, j int) bool {
    34  	strings := sort.StringSlice{string(t[i].prefix), string(t[j].prefix)}
    35  	return strings.Less(0, 1)
    36  }
    37  
    38  func (t tries) Swap(i, j int) {
    39  	t[i], t[j] = t[j], t[i]
    40  }
    41  
    42  type sparseChildList struct {
    43  	children tries
    44  }
    45  
    46  func newSparseChildList(maxChildrenPerSparseNode int) childList {
    47  	return &sparseChildList{
    48  		children: make(tries, 0, maxChildrenPerSparseNode),
    49  	}
    50  }
    51  
    52  func (list *sparseChildList) length() int {
    53  	return len(list.children)
    54  }
    55  
    56  func (list *sparseChildList) head() *Trie {
    57  	return list.children[0]
    58  }
    59  
    60  func (list *sparseChildList) add(child *Trie) childList {
    61  	// Search for an empty spot and insert the child if possible.
    62  	if len(list.children) != cap(list.children) {
    63  		list.children = append(list.children, child)
    64  		return list
    65  	}
    66  
    67  	// Otherwise we have to transform to the dense list type.
    68  	return newDenseChildList(list, child)
    69  }
    70  
    71  func (list *sparseChildList) remove(b byte) {
    72  	for i, node := range list.children {
    73  		if node.prefix[0] == b {
    74  			list.children[i] = list.children[len(list.children)-1]
    75  			list.children[len(list.children)-1] = nil
    76  			list.children = list.children[:len(list.children)-1]
    77  			return
    78  		}
    79  	}
    80  
    81  	// This is not supposed to be reached.
    82  	panic("removing non-existent child")
    83  }
    84  
    85  func (list *sparseChildList) replace(b byte, child *Trie) {
    86  	// Make a consistency check.
    87  	if p0 := child.prefix[0]; p0 != b {
    88  		panic(fmt.Errorf("child prefix mismatch: %v != %v", p0, b))
    89  	}
    90  
    91  	// Seek the child and replace it.
    92  	for i, node := range list.children {
    93  		if node.prefix[0] == b {
    94  			list.children[i] = child
    95  			return
    96  		}
    97  	}
    98  }
    99  
   100  func (list *sparseChildList) next(b byte) *Trie {
   101  	for _, child := range list.children {
   102  		if child.prefix[0] == b {
   103  			return child
   104  		}
   105  	}
   106  	return nil
   107  }
   108  
   109  func (list *sparseChildList) walk(prefix *Prefix, visitor VisitorFunc) error {
   110  
   111  	sort.Sort(list.children)
   112  
   113  	for _, child := range list.children {
   114  		*prefix = append(*prefix, child.prefix...)
   115  		if child.item != nil {
   116  			err := visitor(*prefix, child.item)
   117  			if err != nil {
   118  				if err == SkipSubtree {
   119  					*prefix = (*prefix)[:len(*prefix)-len(child.prefix)]
   120  					continue
   121  				}
   122  				*prefix = (*prefix)[:len(*prefix)-len(child.prefix)]
   123  				return err
   124  			}
   125  		}
   126  
   127  		err := child.children.walk(prefix, visitor)
   128  		*prefix = (*prefix)[:len(*prefix)-len(child.prefix)]
   129  		if err != nil {
   130  			return err
   131  		}
   132  	}
   133  
   134  	return nil
   135  }
   136  
   137  func (list *sparseChildList) total() int {
   138  	tot := 0
   139  	for _, child := range list.children {
   140  		if child != nil {
   141  			tot = tot + child.total()
   142  		}
   143  	}
   144  	return tot
   145  }
   146  
   147  func (list *sparseChildList) clone() childList {
   148  	clones := make(tries, len(list.children), cap(list.children))
   149  	for i, child := range list.children {
   150  		clones[i] = child.Clone()
   151  	}
   152  
   153  	return &sparseChildList{
   154  		children: clones,
   155  	}
   156  }
   157  
   158  func (list *sparseChildList) print(w io.Writer, indent int) {
   159  	for _, child := range list.children {
   160  		if child != nil {
   161  			child.print(w, indent)
   162  		}
   163  	}
   164  }
   165  
   166  type denseChildList struct {
   167  	min         int
   168  	max         int
   169  	numChildren int
   170  	headIndex   int
   171  	children    []*Trie
   172  }
   173  
   174  func newDenseChildList(list *sparseChildList, child *Trie) childList {
   175  	var (
   176  		min int = 255
   177  		max int = 0
   178  	)
   179  	for _, child := range list.children {
   180  		b := int(child.prefix[0])
   181  		if b < min {
   182  			min = b
   183  		}
   184  		if b > max {
   185  			max = b
   186  		}
   187  	}
   188  
   189  	b := int(child.prefix[0])
   190  	if b < min {
   191  		min = b
   192  	}
   193  	if b > max {
   194  		max = b
   195  	}
   196  
   197  	children := make([]*Trie, max-min+1)
   198  	for _, child := range list.children {
   199  		children[int(child.prefix[0])-min] = child
   200  	}
   201  	children[int(child.prefix[0])-min] = child
   202  
   203  	return &denseChildList{
   204  		min:         min,
   205  		max:         max,
   206  		numChildren: list.length() + 1,
   207  		headIndex:   0,
   208  		children:    children,
   209  	}
   210  }
   211  
   212  func (list *denseChildList) length() int {
   213  	return list.numChildren
   214  }
   215  
   216  func (list *denseChildList) head() *Trie {
   217  	return list.children[list.headIndex]
   218  }
   219  
   220  func (list *denseChildList) add(child *Trie) childList {
   221  	b := int(child.prefix[0])
   222  	var i int
   223  
   224  	switch {
   225  	case list.min <= b && b <= list.max:
   226  		if list.children[b-list.min] != nil {
   227  			panic("dense child list collision detected")
   228  		}
   229  		i = b - list.min
   230  		list.children[i] = child
   231  
   232  	case b < list.min:
   233  		children := make([]*Trie, list.max-b+1)
   234  		i = 0
   235  		children[i] = child
   236  		copy(children[list.min-b:], list.children)
   237  		list.children = children
   238  		list.min = b
   239  
   240  	default: // b > list.max
   241  		children := make([]*Trie, b-list.min+1)
   242  		i = b - list.min
   243  		children[i] = child
   244  		copy(children, list.children)
   245  		list.children = children
   246  		list.max = b
   247  	}
   248  
   249  	list.numChildren++
   250  	if i < list.headIndex {
   251  		list.headIndex = i
   252  	}
   253  	return list
   254  }
   255  
   256  func (list *denseChildList) remove(b byte) {
   257  	i := int(b) - list.min
   258  	if list.children[i] == nil {
   259  		// This is not supposed to be reached.
   260  		panic("removing non-existent child")
   261  	}
   262  	list.numChildren--
   263  	list.children[i] = nil
   264  
   265  	// Update head index.
   266  	if i == list.headIndex {
   267  		for ; i < len(list.children); i++ {
   268  			if list.children[i] != nil {
   269  				list.headIndex = i
   270  				return
   271  			}
   272  		}
   273  	}
   274  }
   275  
   276  func (list *denseChildList) replace(b byte, child *Trie) {
   277  	// Make a consistency check.
   278  	if p0 := child.prefix[0]; p0 != b {
   279  		panic(fmt.Errorf("child prefix mismatch: %v != %v", p0, b))
   280  	}
   281  
   282  	// Replace the child.
   283  	list.children[int(b)-list.min] = child
   284  }
   285  
   286  func (list *denseChildList) next(b byte) *Trie {
   287  	i := int(b)
   288  	if i < list.min || list.max < i {
   289  		return nil
   290  	}
   291  	return list.children[i-list.min]
   292  }
   293  
   294  func (list *denseChildList) walk(prefix *Prefix, visitor VisitorFunc) error {
   295  	for _, child := range list.children {
   296  		if child == nil {
   297  			continue
   298  		}
   299  		*prefix = append(*prefix, child.prefix...)
   300  		if child.item != nil {
   301  			if err := visitor(*prefix, child.item); err != nil {
   302  				if err == SkipSubtree {
   303  					*prefix = (*prefix)[:len(*prefix)-len(child.prefix)]
   304  					continue
   305  				}
   306  				*prefix = (*prefix)[:len(*prefix)-len(child.prefix)]
   307  				return err
   308  			}
   309  		}
   310  
   311  		err := child.children.walk(prefix, visitor)
   312  		*prefix = (*prefix)[:len(*prefix)-len(child.prefix)]
   313  		if err != nil {
   314  			return err
   315  		}
   316  	}
   317  
   318  	return nil
   319  }
   320  
   321  func (list *denseChildList) print(w io.Writer, indent int) {
   322  	for _, child := range list.children {
   323  		if child != nil {
   324  			child.print(w, indent)
   325  		}
   326  	}
   327  }
   328  
   329  func (list *denseChildList) clone() childList {
   330  	clones := make(tries, cap(list.children))
   331  
   332  	if list.numChildren != 0 {
   333  		clonedCount := 0
   334  		for i := list.headIndex; i < len(list.children); i++ {
   335  			child := list.children[i]
   336  			if child != nil {
   337  				clones[i] = child.Clone()
   338  				clonedCount++
   339  				if clonedCount == list.numChildren {
   340  					break
   341  				}
   342  			}
   343  		}
   344  	}
   345  
   346  	return &denseChildList{
   347  		min:         list.min,
   348  		max:         list.max,
   349  		numChildren: list.numChildren,
   350  		headIndex:   list.headIndex,
   351  		children:    clones,
   352  	}
   353  }
   354  
   355  func (list *denseChildList) total() int {
   356  	tot := 0
   357  	for _, child := range list.children {
   358  		if child != nil {
   359  			tot = tot + child.total()
   360  		}
   361  	}
   362  	return tot
   363  }