in environment/src/main/kotlin/jetbrains/exodus/tree/patricia/MultiPageImmutableNode.kt [175:248]
public override fun getChildrenRange(b: Byte): NodeChildrenIterator {
val ub = b.unsigned
if (v2Format) {
when (val childrenCount = getChildrenCount()) {
0 -> return EmptyNodeChildrenIterator()
256 -> return ImmutableNodeCompleteChildrenV2Iterator(
ub, ChildReference(b, addressByOffsetV2(ub * childAddressLength))
)
in 1..32 -> {
for (i in 0 until childrenCount) {
val nextByte = byteAt(i)
val next = nextByte.unsigned
if (ub <= next) {
return ImmutableNodeSparseChildrenV2Iterator(
i,
ChildReference(nextByte, addressByOffsetV2(childrenCount + i * childAddressLength))
)
}
}
}
else -> {
val bitsetIdx = ub / Long.SIZE_BITS
val bitset = data.nextLong(bitsetIdx * Long.SIZE_BYTES, Long.SIZE_BYTES)
val bit = ub % Long.SIZE_BITS
val bitmask = 1L shl bit
var index = (bitset and (bitmask - 1L)).countOneBits()
if (bitsetIdx > 0) {
for (i in 0 until bitsetIdx) {
index += data.nextLong(i * Long.SIZE_BYTES, Long.SIZE_BYTES).countOneBits()
}
}
val offset = CHILDREN_BITSET_SIZE_BYTES + index * childAddressLength
if ((bitset and bitmask) != 0L) {
return ImmutableNodeBitsetChildrenV2Iterator(
index, ChildReference(b, addressByOffsetV2(offset))
)
}
if (index < childrenCount) {
return ImmutableNodeBitsetChildrenV2Iterator(
index - 1, ChildReference(b, addressByOffsetV2(offset))
).apply { next() }
}
}
}
} else {
var low = -1
var high = getChildrenCount()
var offset = -1
var resultByte = 0.toByte()
while (high - low > 1) {
val mid = low + high + 1 ushr 1
val off = mid * (childAddressLength + 1)
val actual = byteAt(off)
if (actual.unsigned >= ub) {
offset = off
resultByte = actual
high = mid
} else {
low = mid
}
}
if (offset >= 0) {
val suffixAddress = nextLong(offset + 1)
return ImmutableNodeChildrenIterator(high, ChildReference(resultByte, suffixAddress))
}
}
return EmptyNodeChildrenIterator()
}