Skip to content

Commit

Permalink
simplify
Browse files Browse the repository at this point in the history
  • Loading branch information
gaissmai committed Jan 26, 2025
1 parent ae26d61 commit b72b2c3
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 41 deletions.
34 changes: 15 additions & 19 deletions dumper.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ type nodeType byte

const (
nullNode nodeType = iota // empty node
fullNode // prefixes and (children or PC)
leafNode // no children, only prefixes or PC
intermediateNode // only children, no prefix nor PC,
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
UNKNOWN // logic error
)

Expand All @@ -38,34 +38,30 @@ func (t *Table[V]) dump(w io.Writer) {
return
}

if t.Size4() > 0 {
if t.size4 > 0 {
fmt.Fprintln(w)
fmt.Fprintf(w, "### IPv4: size(%d), nodes(%d)", t.Size4(), t.root4.nodeStatsRec().nodes)
fmt.Fprintf(w, "### IPv4: size(%d), nodes(%d)", t.size4, t.root4.nodeStatsRec().nodes)
t.root4.dumpRec(w, zeroPath, 0, true)
}

if t.Size6() > 0 {
if t.size6 > 0 {
fmt.Fprintln(w)
fmt.Fprintf(w, "### IPv6: size(%d), nodes(%d)", t.Size6(), t.root6.nodeStatsRec().nodes)
fmt.Fprintf(w, "### IPv6: size(%d), nodes(%d)", t.size6, t.root6.nodeStatsRec().nodes)
t.root6.dumpRec(w, zeroPath, 0, false)
}
}

// dumpRec, rec-descent the trie.
func (n *node[V]) dumpRec(w io.Writer, path [16]byte, depth int, is4 bool) {
// dump this node
n.dump(w, path, depth, is4)

// no heap allocs
allChildAddrs := n.children.AsSlice(make([]uint, 0, maxNodeChildren))

// the node may have childs, the rec-descent monster starts
for i, addr := range allChildAddrs {
// the node may have childs, rec-descent down
for i, addr := range n.children.All() {
octet := byte(addr)
path[depth] = octet
switch child := n.children.Items[i].(type) {
case *leaf[V]:
continue
case *node[V]:

if child, ok := n.children.Items[i].(*node[V]); ok {
child.dumpRec(w, path, depth+1, is4)
}
}
Expand All @@ -82,7 +78,7 @@ func (n *node[V]) dump(w io.Writer, path [16]byte, depth int, is4 bool) {

if nPfxCount := n.prefixes.Len(); nPfxCount != 0 {
// no heap allocs
allIndices := n.prefixes.AsSlice(make([]uint, 0, maxNodePrefixes))
allIndices := n.prefixes.All()

// print the baseIndices for this node.
fmt.Fprintf(w, "%sindexs(#%d): %v\n", indent, nPfxCount, allIndices)
Expand Down Expand Up @@ -113,7 +109,7 @@ func (n *node[V]) dump(w io.Writer, path [16]byte, depth int, is4 bool) {
leafAddrs := make([]uint, 0, maxNodeChildren)

// the node has recursive child nodes or path-compressed leaves
for i, addr := range n.children.AsSlice(make([]uint, 0, maxNodeChildren)) {
for i, addr := range n.children.All() {
switch n.children.Items[i].(type) {
case *node[V]:
nodeAddrs = append(nodeAddrs, addr)
Expand Down Expand Up @@ -240,7 +236,7 @@ func (n *node[V]) nodeStats() stats {
s.pfxs = n.prefixes.Len()
s.childs = n.children.Len()

for i := range n.children.AsSlice(make([]uint, 0, maxNodeChildren)) {
for i := range n.children.All() {
switch n.children.Items[i].(type) {
case *node[V]:
s.nodes++
Expand Down
13 changes: 8 additions & 5 deletions internal/bitset/bitset.go
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ func (b BitSet) NextSet(i uint) (uint, bool) {
// AsSlice returns all set bits as slice of uint without
// heap allocations.
//
// This is faster than AppendTo, but also more dangerous,
// This is faster than All, but also more dangerous,
// it panics if the capacity of buf is < b.Size()
func (b BitSet) AsSlice(buf []uint) []uint {
buf = buf[:cap(buf)] // len = cap
Expand All @@ -155,12 +155,15 @@ func (b BitSet) AsSlice(buf []uint) []uint {
return buf
}

// AppendTo appends all set bits to buf and returns the (maybe extended) buf.
// If the capacity of buf is < b.Size() new memory is allocated.
func (b BitSet) AppendTo(buf []uint) []uint {
// All returns all set bits. This is simpler but slower than AsSlice.
func (b BitSet) All() []uint {
buf := make([]uint, b.Size())

slot := 0
for idx, word := range b {
for word != 0 {
buf = append(buf, uint(idx<<6+bits.TrailingZeros64(word)))
buf[slot] = uint(idx<<6 + bits.TrailingZeros64(word))
slot++

// clear the rightmost set bit
word &= word - 1
Expand Down
16 changes: 5 additions & 11 deletions internal/bitset/bitset_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ func TestNil(t *testing.T) {
b.AsSlice(nil)

b = BitSet(nil)
b.AppendTo(nil)
b.All()

b = BitSet(nil)
c := BitSet(nil)
Expand Down Expand Up @@ -100,7 +100,7 @@ func TestZeroValue(t *testing.T) {
b.AsSlice(nil)

b = BitSet{}
b.AppendTo(nil)
b.All()

b = BitSet{}
c := BitSet{}
Expand Down Expand Up @@ -383,50 +383,44 @@ func TestNextSet(t *testing.T) {
}
}

func TestAppendTo(t *testing.T) {
func TestAll(t *testing.T) {
t.Parallel()
testCases := []struct {
name string
//
set []uint
del []uint
//
buf []uint
wantData []uint
}{
{
name: "null",
set: []uint{},
del: []uint{},
buf: nil,
wantData: []uint{},
},
{
name: "zero",
set: []uint{0},
del: []uint{},
buf: nil,
wantData: []uint{0}, // bit #0 is set
},
{
name: "1,5",
set: []uint{1, 5},
del: []uint{},
buf: nil,
wantData: []uint{1, 5},
},
{
name: "many",
set: []uint{1, 65, 130, 190, 250, 300, 380, 420, 480, 511},
del: []uint{},
buf: nil,
wantData: []uint{1, 65, 130, 190, 250, 300, 380, 420, 480, 511},
},
{
name: "special, last return",
set: []uint{1},
del: []uint{1}, // delete without compact
buf: nil,
wantData: []uint{},
},
}
Expand All @@ -441,10 +435,10 @@ func TestAppendTo(t *testing.T) {
b = b.Clear(u) // without compact
}

buf := b.AppendTo(tc.buf)
buf := b.All()

if !slices.Equal(buf, tc.wantData) {
t.Errorf("AppendTo, %s: returned buf is not equal as expected:\ngot: %v\nwant: %v",
t.Errorf("All, %s: returned buf is not equal as expected:\ngot: %v\nwant: %v",
tc.name, buf, tc.wantData)
}
}
Expand Down
8 changes: 2 additions & 6 deletions stringify.go
Original file line number Diff line number Diff line change
Expand Up @@ -168,9 +168,7 @@ func (n *node[V]) getKidsRec(parentIdx uint, path [16]byte, depth int, is4 bool)

var directKids []kid[V]

allIndices := n.prefixes.AsSlice(make([]uint, 0, maxNodePrefixes))

for _, idx := range allIndices {
for _, idx := range n.prefixes.All() {
// parent or self, handled alreday in an upper stack frame.
if idx <= parentIdx {
continue
Expand Down Expand Up @@ -198,9 +196,7 @@ func (n *node[V]) getKidsRec(parentIdx uint, path [16]byte, depth int, is4 bool)
}

// the node may have childs and leaves, the rec-descent monster starts

allChildAddrs := n.children.AsSlice(make([]uint, 0, maxNodeChildren))
for i, addr := range allChildAddrs {
for i, addr := range n.children.All() {
// do a longest-prefix-match
lpmIdx, _, _ := n.lpmGet(hostIndex(addr))
if lpmIdx == parentIdx {
Expand Down

0 comments on commit b72b2c3

Please sign in to comment.