openacid / slim

Surprisingly space efficient trie in Golang(11 bits/key; 100 ns/get).

Home Page:https://openacid.github.io/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

simplify Search() and neighborBranches()

drmingdrmer opened this issue · comments

Describe what to do

Let st.neighborBranches not deal with leaf branch, it should be dealt with outside this function.
This function should only deal with non-leaf branch.
Thus the searching logic would be more clear.

The code shows that: if word == LeafWord then:

  • Return value ltIdx is always -1
  • Return value eqIdx is always eqIdx
  • Return value rtIdx is the first child of current node, or -1(if no child).
  • Return value ltLeaf(indicate if ltIdx is a leaf) is always false

Thus moving logic about leaf out of this function seems better and clear.


func (st *SlimTrie) neighborBranches(idx uint16, word byte) (ltIdx, eqIdx, rtIdx int32, ltLeaf bool) {
	ltIdx, eqIdx, rtIdx = int32(-1), int32(-1), int32(-1)
	ltLeaf = false

	isLeaf := st.Leaves.Has(int32(idx))

	if word == LeafWord {
		if isLeaf {
			eqIdx = int32(idx)
		}
	} else {
		if isLeaf {
			ltIdx = int32(idx)
			ltLeaf = true
		}
	}

	bm, of, found := st.getChild(idx)
	if !found {
		return
	}

	if (bm >> word & 1) == 1 {
		eqIdx = int32(getChildIdx(bm, of, uint16(word)))
	}

	ltStart := word & WordMask
	for i := int8(ltStart) - 1; i >= 0; i-- {
		if (bm >> uint8(i) & 1) == 1 {
			ltIdx = int32(getChildIdx(bm, of, uint16(i)))
			ltLeaf = false
			break
		}
	}

	rtStart := word + 1
	if word == LeafWord {
		rtStart = uint8(0)
	}

	for i := rtStart; i < LeafWord; i++ {
		if (bm >> i & 1) == 1 {
			rtIdx = int32(getChildIdx(bm, of, uint16(i)))
			break
		}
	}

	return
}