Skip to content

Commit

Permalink
make Node struct private
Browse files Browse the repository at this point in the history
  • Loading branch information
ant0ine committed Apr 1, 2013
1 parent 4f174b1 commit aa6221c
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 49 deletions.
61 changes: 30 additions & 31 deletions trie/impl.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ package trie

import (
"errors"
"fmt"
"fmt"
)

func splitParam(remaining string) (string, string) {
Expand All @@ -21,38 +21,37 @@ func splitParam(remaining string) (string, string) {
return remaining[:i], remaining[i:]
}

// A Node of the Trie
type Node struct {
type node struct {
Route interface{}
Children map[string]*Node
Children map[string]*node
ChildrenKeyLen int
ParamChild *Node
ParamChild *node
ParamName string
SplatChild *Node
SplatChild *node
SplatName string
}

func (self *Node) addRoute(path string, route interface{}) error {
func (self *node) addRoute(path string, route interface{}) error {

if len(path) == 0 {
// end of the path, set the Route
if self.Route != nil {
return errors.New("Node.Route already set, duplicated path")
return errors.New("node.Route already set, duplicated path")
}
self.Route = route
return nil
}

token := path[0:1]
remaining := path[1:]
var nextNode *Node
var nextNode *node

if token[0] == ':' {
// :param case
var name string
name, remaining = splitParam(remaining)
if self.ParamChild == nil {
self.ParamChild = &Node{}
self.ParamChild = &node{}
self.ParamName = name
}
nextNode = self.ParamChild
Expand All @@ -61,26 +60,26 @@ func (self *Node) addRoute(path string, route interface{}) error {
name := remaining
remaining = ""
if self.SplatChild == nil {
self.SplatChild = &Node{}
self.SplatChild = &node{}
self.SplatName = name
}
nextNode = self.SplatChild
} else {
// general case
if self.Children == nil {
self.Children = map[string]*Node{}
self.Children = map[string]*node{}
self.ChildrenKeyLen = 1
}
if self.Children[token] == nil {
self.Children[token] = &Node{}
self.Children[token] = &node{}
}
nextNode = self.Children[token]
}

return nextNode.addRoute(remaining, route)
}

// utility for the Node.findRoute recursive method
// utility for the node.findRoute recursive method
type pstack struct {
params []map[string]string
}
Expand All @@ -100,26 +99,26 @@ func (self *pstack) asMap() map[string]string {
r := map[string]string{}
for _, param := range self.params {
for key, value := range param {
if r[key] != "" {
panic(fmt.Sprintf(
"placeholder %s already found, placeholder names should be unique per route",
key,
))
}
if r[key] != "" {
panic(fmt.Sprintf(
"placeholder %s already found, placeholder names should be unique per route",
key,
))
}
r[key] = value
}
}
return r
}

type Match struct {
// same Route as in Node
// same Route as in node
Route interface{}
// map of params matched for this result
Params map[string]string
}

func (self *Node) findRoutes(path string, stack *pstack) []*Match {
func (self *node) findRoutes(path string, stack *pstack) []*Match {

matches := []*Match{}

Expand Down Expand Up @@ -176,7 +175,7 @@ func (self *Node) findRoutes(path string, stack *pstack) []*Match {
return matches
}

func (self *Node) compress() {
func (self *node) compress() {
// *splat branch
if self.SplatChild != nil {
self.SplatChild.compress()
Expand All @@ -198,7 +197,7 @@ func (self *Node) compress() {
}
// compress
if canCompress {
merged := map[string]*Node{}
merged := map[string]*node{}
for key, node := range self.Children {
for gdKey, gdNode := range node.Children {
mergedKey := key + gdKey
Expand All @@ -217,27 +216,27 @@ func (self *Node) compress() {
}

type Trie struct {
Root *Node
root *node
}

// Instanciate a Trie with an empty Node as the root.
// Instanciate a Trie with an empty node as the root.
func New() *Trie {
return &Trie{
Root: &Node{},
root: &node{},
}
}

// Insert the route in the Trie following or creating the Nodes corresponding to the path.
// Insert the route in the Trie following or creating the nodes corresponding to the path.
func (self *Trie) AddRoute(path string, route interface{}) error {
return self.Root.addRoute(path, route)
return self.root.addRoute(path, route)
}

// Given a path, return all the matchin routes.
func (self *Trie) FindRoutes(path string) []*Match {
return self.Root.findRoutes(path, &pstack{})
return self.root.findRoutes(path, &pstack{})
}

// Reduce the size of the tree, must be done after the last AddRoute.
func (self *Trie) Compress() {
self.Root.compress()
self.root.compress()
}
36 changes: 18 additions & 18 deletions trie/impl_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,22 @@ import (
func TestPathInsert(t *testing.T) {

trie := New()
if trie.Root == nil {
if trie.root == nil {
t.Error()
}

trie.AddRoute("/", "1")
if trie.Root.Children["/"] == nil {
if trie.root.Children["/"] == nil {
t.Error()
}

trie.AddRoute("/r", "2")
if trie.Root.Children["/"].Children["r"] == nil {
if trie.root.Children["/"].Children["r"] == nil {
t.Error()
}

trie.AddRoute("/r/", "3")
if trie.Root.Children["/"].Children["r"].Children["/"] == nil {
if trie.root.Children["/"].Children["r"].Children["/"] == nil {
t.Error()
}
}
Expand All @@ -34,54 +34,54 @@ func TestTrieCompression(t *testing.T) {
trie.AddRoute("/adc", "3")

// before compression
if trie.Root.Children["/"].Children["a"].Children["b"].Children["c"] == nil {
if trie.root.Children["/"].Children["a"].Children["b"].Children["c"] == nil {
t.Error()
}
if trie.Root.Children["/"].Children["a"].Children["d"].Children["c"] == nil {
if trie.root.Children["/"].Children["a"].Children["d"].Children["c"] == nil {
t.Error()
}

trie.Compress()

// after compression
if trie.Root.Children["/abc"] == nil {
t.Errorf("%+v", trie.Root)
if trie.root.Children["/abc"] == nil {
t.Errorf("%+v", trie.root)
}
if trie.Root.Children["/adc"] == nil {
t.Errorf("%+v", trie.Root)
if trie.root.Children["/adc"] == nil {
t.Errorf("%+v", trie.root)
}

}
func TestParamInsert(t *testing.T) {
trie := New()

trie.AddRoute("/:id/", "")
if trie.Root.Children["/"].ParamChild.Children["/"] == nil {
if trie.root.Children["/"].ParamChild.Children["/"] == nil {
t.Error()
}
if trie.Root.Children["/"].ParamName != "id" {
if trie.root.Children["/"].ParamName != "id" {
t.Error()
}

trie.AddRoute("/:id/:property.:format", "")
if trie.Root.Children["/"].ParamChild.Children["/"].ParamChild.Children["."].ParamChild == nil {
if trie.root.Children["/"].ParamChild.Children["/"].ParamChild.Children["."].ParamChild == nil {
t.Error()
}
if trie.Root.Children["/"].ParamName != "id" {
if trie.root.Children["/"].ParamName != "id" {
t.Error()
}
if trie.Root.Children["/"].ParamChild.Children["/"].ParamName != "property" {
if trie.root.Children["/"].ParamChild.Children["/"].ParamName != "property" {
t.Error()
}
if trie.Root.Children["/"].ParamChild.Children["/"].ParamChild.Children["."].ParamName != "format" {
if trie.root.Children["/"].ParamChild.Children["/"].ParamChild.Children["."].ParamName != "format" {
t.Error()
}
}

func TestSplatInsert(t *testing.T) {
trie := New()
trie.AddRoute("/*splat", "")
if trie.Root.Children["/"].SplatChild == nil {
if trie.root.Children["/"].SplatChild == nil {
t.Error()
}
}
Expand All @@ -93,7 +93,7 @@ func TestDupeInsert(t *testing.T) {
if err == nil {
t.Error()
}
if trie.Root.Children["/"].Route != "1" {
if trie.root.Children["/"].Route != "1" {
t.Error()
}
}
Expand Down

0 comments on commit aa6221c

Please sign in to comment.