Browse Source

Renamed node types away from temporary assignments.

multiapp-subsubapp
Benjamin Shelton 4 months ago
parent
commit
a0b86e6b02
3 changed files with 81 additions and 81 deletions
  1. +2
    -2
      proxy.go
  2. +52
    -52
      trie.go
  3. +27
    -27
      trie_test.go

+ 2
- 2
proxy.go View File

@ -167,13 +167,13 @@ func (m *mappedLoader) DefaultHandler() http.Handler {
}
type radixLoader struct {
trie *tnode
trie *proxyTrie
def http.Handler
}
func NewRadixLoader(def http.Handler) *radixLoader {
return &radixLoader{
trie: NewTRootNode(),
trie: NewProxyTrie(),
def: def,
}
}


+ 52
- 52
trie.go View File

@ -7,28 +7,28 @@ import (
)
var DefaultMappableNodeFunc = func() mappableNode {
return &binaryTree{} //newMNode()
return &binaryTree{}
}
type mappableNodeFunc func() mappableNode
type mappableNode interface {
Insert(node *tnode)
Insert(node *proxyTrie)
IsEmpty() bool
Lookup(label rune) (*tnode, error)
Lookup(label rune) (*proxyTrie, error)
}
type binaryTree struct {
left *binaryTree
right *binaryTree
node *tnode
node *proxyTrie
}
func BinaryTreeMapperFunc() mappableNode {
return &binaryTree{}
}
func (b *binaryTree) Insert(node *tnode) {
func (b *binaryTree) Insert(node *proxyTrie) {
switch {
// Edge.
case b.node == nil:
@ -62,7 +62,7 @@ func (b *binaryTree) IsEmpty() bool {
return b.left == nil && b.right == nil && b.node == nil
}
func (b *binaryTree) Lookup(label rune) (*tnode, error) {
func (b *binaryTree) Lookup(label rune) (*proxyTrie, error) {
switch {
case b.node == nil:
return nil, fmt.Errorf("not found")
@ -88,32 +88,32 @@ func (b *binaryTree) String() string {
b.left, b.right, b.node)
}
type mnode struct {
keys map[rune]*tnode
type mappedNode struct {
keys map[rune]*proxyTrie
}
func newMNode() *mnode {
return &mnode{
keys: make(map[rune]*tnode),
func NewMappedNode() *mappedNode {
return &mappedNode{
keys: make(map[rune]*proxyTrie),
}
}
func (m *mnode) Insert(node *tnode) {
func (m *mappedNode) Insert(node *proxyTrie) {
if node == nil {
return
}
m.keys[node.label] = node
}
func (m *mnode) IsEmpty() bool {
func (m *mappedNode) IsEmpty() bool {
return len(m.keys) == 0
}
func (m *mnode) String() string {
func (m *mappedNode) String() string {
var out string
if len(m.keys) > 0 {
out += "&mnode{\n"
out += "&mappedNode{\n"
i := 0
for k, v := range m.keys {
i++
@ -122,10 +122,10 @@ func (m *mnode) String() string {
out += "}"
return out
}
return "&mnode{}"
return "&mappedNode{}"
}
func (m *mnode) Lookup(label rune) (*tnode, error) {
func (m *mappedNode) Lookup(label rune) (*proxyTrie, error) {
node, ok := m.keys[label]
if !ok {
return nil, fmt.Errorf("not found")
@ -133,17 +133,17 @@ func (m *mnode) Lookup(label rune) (*tnode, error) {
return node, nil
}
type anode struct {
keys []*tnode
type arrayNode struct {
keys []*proxyTrie
}
func ArrayMapperFunc() mappableNode {
return &anode{
keys: make([]*tnode, 0),
return &arrayNode{
keys: make([]*proxyTrie, 0),
}
}
func (a *anode) Insert(node *tnode) {
func (a *arrayNode) Insert(node *proxyTrie) {
for i := 0; i < len(a.keys); i++ {
if a.keys[i].label == node.label {
a.keys[i].handler = node.handler
@ -153,15 +153,15 @@ func (a *anode) Insert(node *tnode) {
a.keys = append(a.keys, node)
}
func (a *anode) IsEmpty() bool {
func (a *arrayNode) IsEmpty() bool {
return len(a.keys) == 0
}
func (a *anode) String() string {
return "&anode{}"
func (a *arrayNode) String() string {
return "&arrayNode{}"
}
func (a *anode) Lookup(label rune) (*tnode, error) {
func (a *arrayNode) Lookup(label rune) (*proxyTrie, error) {
for i := 0; i < len(a.keys); i++ {
if a.keys[i].label == label {
return a.keys[i], nil
@ -170,7 +170,7 @@ func (a *anode) Lookup(label rune) (*tnode, error) {
return nil, fmt.Errorf("no such key")
}
type tnode struct {
type proxyTrie struct {
// label is the first character matching the current node's prefix.
label rune
@ -185,22 +185,22 @@ type tnode struct {
// of the child nodes' labels. This allows comapratively fast lookups for
// child node prefixes.
keys mappableNode
//children []*tnode
//children []*proxyTrie
KeyFunc func() mappableNode
}
// NewTRootNode returns a root radix trie node.
func NewTRootNode() *tnode {
return &tnode{
keys: newMNode(),
// NewProxyTrie returns a root radix trie node.
func NewProxyTrie() *proxyTrie {
return &proxyTrie{
keys: &binaryTree{},
KeyFunc: DefaultMappableNodeFunc,
}
}
// NewTNode returns a new radix trie node for use within a radix trie root node.
func NewTNode(label rune, prefix string, fn mappableNodeFunc) *tnode {
return &tnode{
// NewTrieNode returns a new radix trie node for use within a radix trie root node.
func NewTrieNode(label rune, prefix string, fn mappableNodeFunc) *proxyTrie {
return &proxyTrie{
label: label,
prefix: prefix,
keys: fn(),
@ -238,7 +238,7 @@ func longestPrefix(s1, s2 string) string {
//
// This function makes additional assignments internally so as to match the
// returned values making their purpose a bit more clear.
func (t *tnode) getEdge(pattern string) (trie *tnode, newPattern string, commonPrefix string, split bool, newLeaf bool) {
func (t *proxyTrie) getEdge(pattern string) (trie *proxyTrie, newPattern string, commonPrefix string, split bool, newLeaf bool) {
var err error
newPattern = pattern
label := rune(newPattern[0])
@ -292,12 +292,12 @@ func (t *tnode) getEdge(pattern string) (trie *tnode, newPattern string, commonP
// Insert a new handler into the trie using pattern `pattern`. Returns the
// generated node.
func (t *tnode) Insert(pattern string, handler http.Handler) *tnode {
func (t *proxyTrie) Insert(pattern string, handler http.Handler) *proxyTrie {
edge, newpattern, common, split, newLeaf := t.getEdge(pattern)
// Root node detection.
if edge.label == rune(0) && edge.prefix == "" {
node := NewTNode(rune(pattern[0]), pattern, t.KeyFunc)
node := NewTrieNode(rune(pattern[0]), pattern, t.KeyFunc)
node.handler = handler
edge.keys.Insert(node)
return node
@ -325,7 +325,7 @@ func (t *tnode) Insert(pattern string, handler http.Handler) *tnode {
// the incoming pattern is simply "ab" since we need to split the prefix
// ("ab") and create a new node with the old suffix ("c").
if rightPrefix == "" {
node := NewTNode(rune(leftPrefix[0]), leftPrefix, t.KeyFunc)
node := NewTrieNode(rune(leftPrefix[0]), leftPrefix, t.KeyFunc)
node.handler = edge.handler
node.keys = edge.keys
edge.prefix = common
@ -346,8 +346,8 @@ func (t *tnode) Insert(pattern string, handler http.Handler) *tnode {
// Do not mistake left and right for a binary radix trie, which this is
// not. This is just inline semantics to make it easier to reaspon about
// when the edge nodes are re-parented.
lnode := NewTNode(rune(leftPrefix[0]), leftPrefix, t.KeyFunc)
rnode := NewTNode(rune(rightPrefix[0]), rightPrefix, t.KeyFunc)
lnode := NewTrieNode(rune(leftPrefix[0]), leftPrefix, t.KeyFunc)
rnode := NewTrieNode(rune(rightPrefix[0]), rightPrefix, t.KeyFunc)
lnode.handler = edge.handler
rnode.handler = handler
@ -364,7 +364,7 @@ func (t *tnode) Insert(pattern string, handler http.Handler) *tnode {
} else {
// No node split is required so we simply attach a new node to the
// current edge.
node := NewTNode(rune(newpattern[0]), newpattern, t.KeyFunc)
node := NewTrieNode(rune(newpattern[0]), newpattern, t.KeyFunc)
node.handler = handler
edge.keys.Insert(node)
}
@ -373,24 +373,24 @@ func (t *tnode) Insert(pattern string, handler http.Handler) *tnode {
}
// IsEdge returns whether the node is an edge node.
func (t *tnode) IsEdge() bool {
func (t *proxyTrie) IsEdge() bool {
return t.handler == nil
}
// IsLeaf returns whether the node is a leaf node.
func (t *tnode) IsLeaf() bool {
func (t *proxyTrie) IsLeaf() bool {
return t.handler != nil
}
// IsRoot returns whether the node is the root node.
func (t *tnode) IsRoot() bool {
func (t *proxyTrie) IsRoot() bool {
return t.label == rune(0) && t.prefix == "" && t.handler == nil
}
// Lookup accepts a single pattern string and traverses the radix trie,
// returning the handler associated with the pattern or nil if the pattern
// cannot be found.
func (t *tnode) Lookup(pattern string) http.Handler {
func (t *proxyTrie) Lookup(pattern string) http.Handler {
n := t.lookup(pattern)
if n != nil {
return n.handler
@ -398,7 +398,7 @@ func (t *tnode) Lookup(pattern string) http.Handler {
return nil
}
func (t *tnode) lookup(pattern string) *tnode {
func (t *proxyTrie) lookup(pattern string) *proxyTrie {
var err error
node := t
label := rune(pattern[0])
@ -457,8 +457,8 @@ func (t *tnode) lookup(pattern string) *tnode {
// your application around it as it is currently path agnostic. Care must be
// taken to ensure that the handlers attached to any given pattern will fail as
// expected when passed unexpected URLs.
func (t *tnode) LongestMatch(pattern string) http.Handler {
var last *tnode
func (t *proxyTrie) LongestMatch(pattern string) http.Handler {
var last *proxyTrie
var err error
node := t
last = node
@ -497,13 +497,13 @@ func (t *tnode) LongestMatch(pattern string) http.Handler {
}
// String representation of the trie.
func (t *tnode) String() string {
return fmt.Sprintf(`&tnode{label="%c", prefix="%s", handler="%v" keys="%v"}`,
func (t *proxyTrie) String() string {
return fmt.Sprintf(`&proxyTrie{label="%c", prefix="%s", handler="%v" keys="%v"}`,
t.label, t.prefix, t.handler, t.keys)
}
// SwitchKeyFunc changes the keying function to fn.
func (t *tnode) SwitchKeyFunc(fn mappableNodeFunc) {
func (t *proxyTrie) SwitchKeyFunc(fn mappableNodeFunc) {
t.keys = fn()
t.KeyFunc = fn
}

+ 27
- 27
trie_test.go View File

@ -70,11 +70,11 @@ func initProxyTrie() error {
func Test_BTree(t *testing.T) {
root := &binaryTree{}
a_node := NewTNode('a', "", DefaultMappableNodeFunc)
b_node := NewTNode('b', "", DefaultMappableNodeFunc)
c_node := NewTNode('c', "", DefaultMappableNodeFunc)
d_node := NewTNode('d', "", DefaultMappableNodeFunc)
e_node := NewTNode('e', "", DefaultMappableNodeFunc)
a_node := NewTrieNode('a', "", DefaultMappableNodeFunc)
b_node := NewTrieNode('b', "", DefaultMappableNodeFunc)
c_node := NewTrieNode('c', "", DefaultMappableNodeFunc)
d_node := NewTrieNode('d', "", DefaultMappableNodeFunc)
e_node := NewTrieNode('e', "", DefaultMappableNodeFunc)
root.Insert(a_node)
root.Insert(b_node)
@ -125,11 +125,11 @@ func Test_BTree(t *testing.T) {
func Test_BTreeOverwrite(t *testing.T) {
root := &binaryTree{}
a_node := NewTNode('a', "", DefaultMappableNodeFunc)
b_node := NewTNode('b', "", DefaultMappableNodeFunc)
c_node := NewTNode('c', "", DefaultMappableNodeFunc)
d_node := NewTNode('d', "", DefaultMappableNodeFunc)
e_node := NewTNode('e', "", DefaultMappableNodeFunc)
a_node := NewTrieNode('a', "", DefaultMappableNodeFunc)
b_node := NewTrieNode('b', "", DefaultMappableNodeFunc)
c_node := NewTrieNode('c', "", DefaultMappableNodeFunc)
d_node := NewTrieNode('d', "", DefaultMappableNodeFunc)
e_node := NewTrieNode('e', "", DefaultMappableNodeFunc)
a_node.handler = &testHandler{1}
@ -139,7 +139,7 @@ func Test_BTreeOverwrite(t *testing.T) {
root.Insert(d_node)
root.Insert(e_node)
a_overwrite := NewTNode('a', "", DefaultMappableNodeFunc)
a_overwrite := NewTrieNode('a', "", DefaultMappableNodeFunc)
a_overwrite.handler = &testHandler{2}
root.Insert(a_overwrite)
@ -177,7 +177,7 @@ func Test_LongestPrefix(t *testing.T) {
}
func Test_TrieInsert(t *testing.T) {
node := NewTRootNode()
node := NewProxyTrie()
node.Insert("testing", &testHandler{1})
node.Insert("test", &testHandler{2})
node.Insert("testings", &testHandler{3})
@ -350,7 +350,7 @@ func buildWordList(count int) ([]string, error) {
}
func Test_RadixTrieLongestMatch(t *testing.T) {
node := NewTRootNode()
node := NewProxyTrie()
node.Insert("subapp.example.com/testing", &testHandler{0})
node.Insert("subapp.example.com/testing/again", &testHandler{1})
@ -398,7 +398,7 @@ func Test_RadixTrieLongestMatch(t *testing.T) {
// tests multiple possible prefixes and duplicate characters. This test also
// uses the radix trie directly and doesn't bind to a server instance.
func Test_RadixTrieLongestMatch2(t *testing.T) {
node := NewTRootNode()
node := NewProxyTrie()
patterns := []string{
"app.example.com/a",
@ -494,7 +494,7 @@ func Test_TrieTester(t *testing.T) {
//"example.com/app",
}
node := NewTRootNode()
node := NewProxyTrie()
for i, word := range words {
node.Insert(word, &testHandler{i})
@ -506,7 +506,7 @@ func Test_TrieTester(t *testing.T) {
}
func Test_DictionaryInsertAndLookup(t *testing.T) {
node := NewTRootNode()
node := NewProxyTrie()
for i, word := range wordList {
node.Insert(word, &testHandler{i})
@ -529,7 +529,7 @@ func Test_DictionaryInsertAndLookup(t *testing.T) {
func Test_RadixTrieInsertOverwrite(t *testing.T) {
// Overwrite not currently supported.
return
node := NewTRootNode()
node := NewProxyTrie()
handler := &testHandler{1}
node.Insert("testing", handler)
@ -547,7 +547,7 @@ func Test_RadixTrieInsertOverwrite(t *testing.T) {
}
}
node = NewTRootNode()
node = NewProxyTrie()
node.Insert("testing", &testHandler{0})
node.Insert("testing", &testHandler{1})
@ -569,7 +569,7 @@ func Test_RadixTrieInsertOverwrite(t *testing.T) {
}
func Benchmark_RadixTrieLookupMap(b *testing.B) {
node := NewTRootNode()
node := NewProxyTrie()
for i, word := range wordList {
node.Insert(word, &testHandler{i})
@ -585,7 +585,7 @@ func Benchmark_RadixTrieLookupMap(b *testing.B) {
}
func Benchmark_RadixTrieLookupBinaryTree(b *testing.B) {
node := NewTRootNode()
node := NewProxyTrie()
node.KeyFunc = BinaryTreeMapperFunc
for i, word := range wordList {
@ -602,7 +602,7 @@ func Benchmark_RadixTrieLookupBinaryTree(b *testing.B) {
}
func Benchmark_RadixTrieLookupArray(b *testing.B) {
node := NewTRootNode()
node := NewProxyTrie()
node.KeyFunc = ArrayMapperFunc
for i, word := range wordList {
@ -638,7 +638,7 @@ func Benchmark_MapLookup(b *testing.B) {
}
func Benchmark_RadixTrieHugeLookupMap(b *testing.B) {
node := NewTRootNode()
node := NewProxyTrie()
var list words
list, _ = buildWordList(100000)
@ -657,7 +657,7 @@ func Benchmark_RadixTrieHugeLookupMap(b *testing.B) {
}
func Benchmark_RadixTrieHugeLookupBinaryTree(b *testing.B) {
node := NewTRootNode()
node := NewProxyTrie()
node.KeyFunc = BinaryTreeMapperFunc
var list words
@ -677,7 +677,7 @@ func Benchmark_RadixTrieHugeLookupBinaryTree(b *testing.B) {
}
func Benchmark_RadixTrieHugeLookupArray(b *testing.B) {
node := NewTRootNode()
node := NewProxyTrie()
node.KeyFunc = ArrayMapperFunc
var list words
@ -718,7 +718,7 @@ func Benchmark_HugeMapLookup(b *testing.B) {
}
}
func Benchmark_RadixTriePrefixLookupMap(b *testing.B) {
node := NewTRootNode()
node := NewProxyTrie()
for i, word := range prefixList {
node.Insert(word, &testHandler{i})
@ -734,7 +734,7 @@ func Benchmark_RadixTriePrefixLookupMap(b *testing.B) {
}
func Benchmark_RadixTriePrefixLookupBinaryTree(b *testing.B) {
node := NewTRootNode()
node := NewProxyTrie()
node.KeyFunc = BinaryTreeMapperFunc
for i, word := range prefixList {
@ -751,7 +751,7 @@ func Benchmark_RadixTriePrefixLookupBinaryTree(b *testing.B) {
}
func Benchmark_RadixTriePrefixLookupArray(b *testing.B) {
node := NewTRootNode()
node := NewProxyTrie()
node.KeyFunc = ArrayMapperFunc
for i, word := range prefixList {


Loading…
Cancel
Save