Correct and simplify textBuf drawing using the new ViewsFromTo+ new ring funcs

This commit is contained in:
bloeys
2022-07-23 03:08:44 +04:00
parent 76992472d4
commit 641e3eda98
6 changed files with 199 additions and 37 deletions

View File

@ -91,9 +91,24 @@ func clamp[T constraints.Ordered](x, min, max T) T {
return x
}
// Get returns the element at the index relative from Buffer.Start
// If there are no elements then the default value of T is returned
func (b *Buffer[T]) Get(index uint64) (val T) {
if index >= uint64(b.Len) {
return val
}
return b.Data[(b.Start+int64(index))%b.Cap]
}
func (b *Buffer[T]) AbsIndex(relIndex uint64) uint64 {
return uint64((b.Start + int64(relIndex)) % b.Cap)
}
// Views returns two slices that have 'Len' elements in total between them.
// The first slice is from Start till min(Start+Len, Cap). If Start+Len<=Cap then the first slice contains all the data and the second is empty.
// If Start+Len>Cap then the first slice contains the data from Start till Cap, and the second slice contains data from Zero till Start+Len-Cap (basically the remaining elements to reach Len in total)
// If Start+Len>Cap then the first slice contains the data from Start till Cap, and the second slice contains data from 0 till Start+Len-Cap (basically the remaining elements to reach Len in total)
//
// This function does NOT copy. Any changes on the returned slices will reflect on the buffer Data
//
@ -109,15 +124,49 @@ func (b *Buffer[T]) Views() (v1, v2 []T) {
return
}
func (b *Buffer[T]) Iterator() Iterator[T] {
func (b *Buffer[T]) ViewsFromTo(fromIndex, toIndex uint64) (v1, v2 []T) {
v1, v2 := b.Views()
return Iterator[T]{
V1: v1,
V2: v2,
Curr: 0,
InV1: true,
toIndex++ // We convert the index into a length (e.g. from=0, to=0 is from=0, len=1)
if toIndex <= fromIndex || fromIndex >= uint64(b.Len) {
return []T{}, []T{}
}
v1, v2 = b.Views()
v1Len := uint64(len(v1))
v2Len := uint64(len(v2))
startInV1 := fromIndex < v1Len
if startInV1 {
if toIndex <= v1Len {
v1 = v1[fromIndex:toIndex]
v2 = v2[:0]
return
}
toIndex -= v1Len
if toIndex > v2Len {
toIndex = v2Len
}
v1 = v1[fromIndex:v1Len]
v2 = v2[:toIndex]
return
}
fromIndex -= v1Len - 1
toIndex -= v1Len
if toIndex >= v2Len {
toIndex = v2Len
}
v1 = v1[:0]
v2 = v2[fromIndex:toIndex]
return
}
func (b *Buffer[T]) Iterator() Iterator[T] {
return NewIterator(b)
}
func NewBuffer[T any](capacity uint64) *Buffer[T] {
@ -263,7 +312,7 @@ func (it *Iterator[T]) PrevN(buf []T, n int) (read int, done bool) {
// and the next Prev() call returns done=true
func (it *Iterator[T]) GotoStart() {
it.Curr = 0
it.InV1 = true
it.InV1 = len(it.V1) > 0
}
// GotoIndex goes to the index n relative to Buffer.Start
@ -297,3 +346,13 @@ func (it *Iterator[T]) GotoEnd() {
it.Curr = int64(len(it.V2))
it.InV1 = false
}
func NewIterator[T any](b *Buffer[T]) Iterator[T] {
v1, v2 := b.Views()
return Iterator[T]{
V1: v1,
V2: v2,
Curr: 0,
InV1: len(v1) > 0, // If buffer is empty we shouldn't be in V1
}
}

View File

@ -87,6 +87,78 @@ func TestRing(t *testing.T) {
b2.DeleteN(2, 1)
Check(t, 3, b2.Len)
CheckArr(t, []int{5, 6, 8, 8}, b2.Data)
// ViewsFromTo
b2 = ring.NewBuffer[int](4)
v11, v22 := b2.ViewsFromTo(0, 0)
Check(t, 0, len(v11))
Check(t, 0, len(v22))
b2.Write(1, 2, 3, 4)
v11, v22 = b2.ViewsFromTo(5, 0)
Check(t, 0, len(v11))
Check(t, 0, len(v22))
v11, v22 = b2.ViewsFromTo(0, 0)
Check(t, 1, len(v11))
Check(t, 0, len(v22))
CheckArr(t, []int{1}, v11)
v11, v22 = b2.ViewsFromTo(0, 1)
Check(t, 2, len(v11))
Check(t, 0, len(v22))
CheckArr(t, []int{1, 2}, v11)
v11, v22 = b2.ViewsFromTo(0, 3)
Check(t, 4, len(v11))
Check(t, 0, len(v22))
CheckArr(t, []int{1, 2, 3, 4}, v11)
v11, v22 = b2.ViewsFromTo(0, 4)
Check(t, 4, len(v11))
Check(t, 0, len(v22))
CheckArr(t, []int{1, 2, 3, 4}, v11)
v11, v22 = b2.ViewsFromTo(0, 40)
Check(t, 4, len(v11))
Check(t, 0, len(v22))
CheckArr(t, []int{1, 2, 3, 4}, v11)
v11, v22 = b2.ViewsFromTo(3, 40)
Check(t, 1, len(v11))
Check(t, 0, len(v22))
CheckArr(t, []int{4}, v11)
b2.Write(5, 6)
v11, v22 = b2.ViewsFromTo(3, 40)
Check(t, 0, len(v11))
Check(t, 0, len(v22))
v11, v22 = b2.ViewsFromTo(1, 2)
Check(t, 1, len(v11))
Check(t, 1, len(v22))
CheckArr(t, []int{4}, v11)
CheckArr(t, []int{5}, v22)
v11, v22 = b2.ViewsFromTo(0, 1)
Check(t, 2, len(v11))
Check(t, 0, len(v22))
CheckArr(t, []int{3, 4}, v11)
v11, v22 = b2.ViewsFromTo(0, 2)
Check(t, 2, len(v11))
Check(t, 1, len(v22))
CheckArr(t, []int{3, 4}, v11)
CheckArr(t, []int{5}, v22)
v11, v22 = b2.ViewsFromTo(0, 3)
Check(t, 2, len(v11))
Check(t, 2, len(v22))
CheckArr(t, []int{3, 4}, v11)
CheckArr(t, []int{5, 6}, v22)
}
func TestIterator(t *testing.T) {
@ -198,6 +270,23 @@ func TestIterator(t *testing.T) {
ans = []int{4, 3}
it.PrevN(got, 2)
CheckArr(t, ans, got)
// Empty buffer
b = ring.NewBuffer[int](4)
it = b.Iterator()
Check(t, 0, len(it.V1))
Check(t, 0, len(it.V2))
Check(t, false, it.InV1)
it.GotoStart()
Check(t, false, it.InV1)
it.GotoIndex(1)
Check(t, false, it.InV1)
_, done := it.Next()
Check(t, true, done)
}
func Check[T comparable](t *testing.T, expected, got T) {