Update dependencies
This commit is contained in:
253
vendor/github.com/gaissmai/bart/dumper.go
generated
vendored
253
vendor/github.com/gaissmai/bart/dumper.go
generated
vendored
@@ -14,9 +14,9 @@ type nodeType byte
|
||||
|
||||
const (
|
||||
nullNode nodeType = iota // empty node
|
||||
fullNode // prefixes and children
|
||||
leafNode // only prefixes
|
||||
intermediateNode // only children
|
||||
fullNode // prefixes and children or path-compressed prefixes
|
||||
leafNode // no children, only prefixes or path-compressed prefixes
|
||||
intermediateNode // only children, no prefix nor path-compressed prefixes
|
||||
)
|
||||
|
||||
// ##################################################
|
||||
@@ -27,65 +27,47 @@ const (
|
||||
func (t *Table[V]) dumpString() string {
|
||||
w := new(strings.Builder)
|
||||
t.dump(w)
|
||||
|
||||
return w.String()
|
||||
}
|
||||
|
||||
// dump the table structure and all the nodes to w.
|
||||
//
|
||||
// Output:
|
||||
//
|
||||
// [FULL] depth: 0 path: [] / 0
|
||||
// indexs(#6): 1 66 128 133 266 383
|
||||
// prefxs(#6): 0/0 8/6 0/7 10/7 10/8 127/8
|
||||
// childs(#3): 10 127 192
|
||||
//
|
||||
// .[IMED] depth: 1 path: [10] / 8
|
||||
// .childs(#1): 0
|
||||
//
|
||||
// ..[LEAF] depth: 2 path: [10.0] / 16
|
||||
// ..indexs(#2): 256 257
|
||||
// ..prefxs(#2): 0/8 1/8
|
||||
//
|
||||
// .[IMED] depth: 1 path: [127] / 8
|
||||
// .childs(#1): 0
|
||||
//
|
||||
// ..[IMED] depth: 2 path: [127.0] / 16
|
||||
// ..childs(#1): 0
|
||||
//
|
||||
// ...[LEAF] depth: 3 path: [127.0.0] / 24
|
||||
// ...indexs(#1): 257
|
||||
// ...prefxs(#1): 1/8
|
||||
//
|
||||
// ...
|
||||
func (t *Table[V]) dump(w io.Writer) {
|
||||
t.init()
|
||||
if t == nil {
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Fprint(w, "### IPv4:")
|
||||
t.rootV4.dumpRec(w, zeroPath, 0, true)
|
||||
if t.size4 > 0 {
|
||||
fmt.Fprintln(w)
|
||||
fmt.Fprintf(w, "### IPv4: size(%d), nodes(%d)", t.size4, t.root4.nodeStatsRec().nodes)
|
||||
t.root4.dumpRec(w, stridePath{}, 0, true)
|
||||
}
|
||||
|
||||
fmt.Fprint(w, "### IPv6:")
|
||||
t.rootV6.dumpRec(w, zeroPath, 0, false)
|
||||
if t.size6 > 0 {
|
||||
fmt.Fprintln(w)
|
||||
fmt.Fprintf(w, "### IPv6: size(%d), nodes(%d)", t.size6, t.root6.nodeStatsRec().nodes)
|
||||
t.root6.dumpRec(w, stridePath{}, 0, false)
|
||||
}
|
||||
}
|
||||
|
||||
// dumpRec, rec-descent the trie.
|
||||
func (n *node[V]) dumpRec(w io.Writer, path [16]byte, depth int, is4 bool) {
|
||||
func (n *node[V]) dumpRec(w io.Writer, path stridePath, depth int, is4 bool) {
|
||||
// dump this node
|
||||
n.dump(w, path, depth, is4)
|
||||
|
||||
// make backing arrays, no heap allocs
|
||||
addrBackingArray := [maxNodeChildren]uint{}
|
||||
|
||||
// the node may have childs, the rec-descent monster starts
|
||||
for i, addr := range n.allChildAddrs(addrBackingArray[:]) {
|
||||
// the node may have childs, rec-descent down
|
||||
for i, addr := range n.children.All() {
|
||||
octet := byte(addr)
|
||||
child := n.children[i]
|
||||
path[depth] = octet
|
||||
|
||||
child.dumpRec(w, path, depth+1, is4)
|
||||
if child, ok := n.children.Items[i].(*node[V]); ok {
|
||||
child.dumpRec(w, path, depth+1, is4)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// dump the node to w.
|
||||
func (n *node[V]) dump(w io.Writer, path [16]byte, depth int, is4 bool) {
|
||||
func (n *node[V]) dump(w io.Writer, path stridePath, depth int, is4 bool) {
|
||||
bits := depth * strideLen
|
||||
indent := strings.Repeat(".", depth)
|
||||
|
||||
@@ -93,42 +75,97 @@ func (n *node[V]) dump(w io.Writer, path [16]byte, depth int, is4 bool) {
|
||||
fmt.Fprintf(w, "\n%s[%s] depth: %d path: [%s] / %d\n",
|
||||
indent, n.hasType(), depth, ipStridePath(path, depth, is4), bits)
|
||||
|
||||
if nPfxLen := len(n.prefixes); nPfxLen != 0 {
|
||||
// make backing arrays, no heap allocs
|
||||
idxBackingArray := [maxNodePrefixes]uint{}
|
||||
allIndices := n.allStrideIndexes(idxBackingArray[:])
|
||||
if nPfxCount := n.prefixes.Len(); nPfxCount != 0 {
|
||||
// no heap allocs
|
||||
allIndices := n.prefixes.All()
|
||||
|
||||
// print the baseIndices for this node.
|
||||
fmt.Fprintf(w, "%sindexs(#%d): %v\n", indent, nPfxLen, allIndices)
|
||||
fmt.Fprintf(w, "%sindexs(#%d): %v\n", indent, nPfxCount, allIndices)
|
||||
|
||||
// print the prefixes for this node
|
||||
fmt.Fprintf(w, "%sprefxs(#%d):", indent, nPfxLen)
|
||||
fmt.Fprintf(w, "%sprefxs(#%d):", indent, nPfxCount)
|
||||
|
||||
for _, idx := range allIndices {
|
||||
octet, bits := baseIndexToPrefix(idx)
|
||||
fmt.Fprintf(w, " %s/%d", octetFmt(octet, is4), bits)
|
||||
octet, pfxLen := idxToPfx(idx)
|
||||
fmt.Fprintf(w, " %s/%d", octetFmt(octet, is4), pfxLen)
|
||||
}
|
||||
|
||||
fmt.Fprintln(w)
|
||||
|
||||
// print the values for this node
|
||||
fmt.Fprintf(w, "%svalues(#%d):", indent, nPfxLen)
|
||||
fmt.Fprintf(w, "%svalues(#%d):", indent, nPfxCount)
|
||||
|
||||
for _, val := range n.prefixes {
|
||||
for _, val := range n.prefixes.Items {
|
||||
fmt.Fprintf(w, " %v", val)
|
||||
}
|
||||
|
||||
fmt.Fprintln(w)
|
||||
}
|
||||
|
||||
if childs := len(n.children); childs != 0 {
|
||||
// print the childs for this node
|
||||
fmt.Fprintf(w, "%schilds(#%d):", indent, childs)
|
||||
if n.children.Len() != 0 {
|
||||
|
||||
addrBackingArray := [maxNodeChildren]uint{}
|
||||
for _, addr := range n.allChildAddrs(addrBackingArray[:]) {
|
||||
octet := byte(addr)
|
||||
fmt.Fprintf(w, " %s", octetFmt(octet, is4))
|
||||
nodeAddrs := make([]uint, 0, maxNodeChildren)
|
||||
leafAddrs := make([]uint, 0, maxNodeChildren)
|
||||
|
||||
// the node has recursive child nodes or path-compressed leaves
|
||||
for i, addr := range n.children.All() {
|
||||
switch n.children.Items[i].(type) {
|
||||
case *node[V]:
|
||||
nodeAddrs = append(nodeAddrs, addr)
|
||||
continue
|
||||
|
||||
case *leaf[V]:
|
||||
leafAddrs = append(leafAddrs, addr)
|
||||
|
||||
default:
|
||||
panic("logic error, wrong node type")
|
||||
}
|
||||
}
|
||||
fmt.Fprintln(w)
|
||||
|
||||
if nodeCount := len(nodeAddrs); nodeCount > 0 {
|
||||
// print the childs for this node
|
||||
fmt.Fprintf(w, "%schilds(#%d):", indent, nodeCount)
|
||||
|
||||
for _, addr := range nodeAddrs {
|
||||
octet := byte(addr)
|
||||
fmt.Fprintf(w, " %s", octetFmt(octet, is4))
|
||||
}
|
||||
|
||||
fmt.Fprintln(w)
|
||||
}
|
||||
|
||||
if leafCount := len(leafAddrs); leafCount > 0 {
|
||||
// print the pathcomp prefixes for this node
|
||||
fmt.Fprintf(w, "%sleaves(#%d):", indent, leafCount)
|
||||
|
||||
for _, addr := range leafAddrs {
|
||||
octet := byte(addr)
|
||||
k := n.children.MustGet(addr)
|
||||
pc := k.(*leaf[V])
|
||||
|
||||
fmt.Fprintf(w, " %s:{%s, %v}", octetFmt(octet, is4), pc.prefix, pc.value)
|
||||
}
|
||||
fmt.Fprintln(w)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// hasType returns the nodeType.
|
||||
func (n *node[V]) hasType() nodeType {
|
||||
s := n.nodeStats()
|
||||
|
||||
switch {
|
||||
case s.pfxs == 0 && s.childs == 0:
|
||||
return nullNode
|
||||
case s.nodes == 0:
|
||||
return leafNode
|
||||
case (s.pfxs > 0 || s.leaves > 0) && s.nodes > 0:
|
||||
return fullNode
|
||||
case (s.pfxs == 0 && s.leaves == 0) && s.nodes > 0:
|
||||
return intermediateNode
|
||||
default:
|
||||
panic(fmt.Sprintf("UNREACHABLE: pfx: %d, chld: %d, node: %d, leaf: %d",
|
||||
s.pfxs, s.childs, s.nodes, s.leaves))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -137,6 +174,7 @@ func octetFmt(octet byte, is4 bool) string {
|
||||
if is4 {
|
||||
return fmt.Sprintf("%d", octet)
|
||||
}
|
||||
|
||||
return fmt.Sprintf("0x%02x", octet)
|
||||
}
|
||||
|
||||
@@ -144,7 +182,7 @@ func octetFmt(octet byte, is4 bool) string {
|
||||
//
|
||||
// 127.0.0
|
||||
// 2001:0d
|
||||
func ipStridePath(path [16]byte, depth int, is4 bool) string {
|
||||
func ipStridePath(path stridePath, depth int, is4 bool) string {
|
||||
buf := new(strings.Builder)
|
||||
|
||||
if is4 {
|
||||
@@ -152,8 +190,10 @@ func ipStridePath(path [16]byte, depth int, is4 bool) string {
|
||||
if i != 0 {
|
||||
buf.WriteString(".")
|
||||
}
|
||||
|
||||
buf.WriteString(strconv.Itoa(int(b)))
|
||||
}
|
||||
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
@@ -161,8 +201,10 @@ func ipStridePath(path [16]byte, depth int, is4 bool) string {
|
||||
if i != 0 && i%2 == 0 {
|
||||
buf.WriteString(":")
|
||||
}
|
||||
|
||||
buf.WriteString(fmt.Sprintf("%02x", b))
|
||||
}
|
||||
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
@@ -177,29 +219,72 @@ func (nt nodeType) String() string {
|
||||
return "LEAF"
|
||||
case intermediateNode:
|
||||
return "IMED"
|
||||
default:
|
||||
return "unreachable"
|
||||
}
|
||||
panic("unreachable")
|
||||
}
|
||||
|
||||
// hasType returns the nodeType.
|
||||
func (n *node[V]) hasType() nodeType {
|
||||
lenPefixes := len(n.prefixes)
|
||||
lenChilds := len(n.children)
|
||||
|
||||
if lenPefixes == 0 && lenChilds != 0 {
|
||||
return intermediateNode
|
||||
}
|
||||
|
||||
if lenPefixes == 0 && lenChilds == 0 {
|
||||
return nullNode
|
||||
}
|
||||
|
||||
if lenPefixes != 0 && lenChilds == 0 {
|
||||
return leafNode
|
||||
}
|
||||
|
||||
if lenPefixes != 0 && lenChilds != 0 {
|
||||
return fullNode
|
||||
}
|
||||
panic("unreachable")
|
||||
// stats, only used for dump, tests and benchmarks
|
||||
type stats struct {
|
||||
pfxs int
|
||||
childs int
|
||||
nodes int
|
||||
leaves int
|
||||
}
|
||||
|
||||
// node statistics for this single node
|
||||
func (n *node[V]) nodeStats() stats {
|
||||
var s stats
|
||||
|
||||
s.pfxs = n.prefixes.Len()
|
||||
s.childs = n.children.Len()
|
||||
|
||||
for i := range n.children.All() {
|
||||
switch n.children.Items[i].(type) {
|
||||
case *node[V]:
|
||||
s.nodes++
|
||||
|
||||
case *leaf[V]:
|
||||
s.leaves++
|
||||
|
||||
default:
|
||||
panic("logic error, wrong node type")
|
||||
}
|
||||
}
|
||||
|
||||
return s
|
||||
}
|
||||
|
||||
// nodeStatsRec, calculate the number of pfxs, nodes and leaves under n, rec-descent.
|
||||
func (n *node[V]) nodeStatsRec() stats {
|
||||
var s stats
|
||||
if n == nil || n.isEmpty() {
|
||||
return s
|
||||
}
|
||||
|
||||
s.pfxs = n.prefixes.Len()
|
||||
s.childs = n.children.Len()
|
||||
s.nodes = 1 // this node
|
||||
s.leaves = 0
|
||||
|
||||
for _, kidAny := range n.children.Items {
|
||||
switch kid := kidAny.(type) {
|
||||
case *node[V]:
|
||||
// rec-descent
|
||||
rs := kid.nodeStatsRec()
|
||||
|
||||
s.pfxs += rs.pfxs
|
||||
s.childs += rs.childs
|
||||
s.nodes += rs.nodes
|
||||
s.leaves += rs.leaves
|
||||
|
||||
case *leaf[V]:
|
||||
s.leaves++
|
||||
|
||||
default:
|
||||
panic("logic error, wrong node type")
|
||||
}
|
||||
}
|
||||
|
||||
return s
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user