mirror of
https://github.com/anyproto/any-sync.git
synced 2025-06-08 14:07:02 +09:00
93 lines
1.7 KiB
Go
93 lines
1.7 KiB
Go
package objecttree
|
|
|
|
import (
|
|
"sync"
|
|
)
|
|
|
|
var itPool = &sync.Pool{
|
|
New: func() interface{} {
|
|
return &iterator{
|
|
stack: make([]*Change, 0, 100),
|
|
resBuf: make([]*Change, 0, 100),
|
|
}
|
|
},
|
|
}
|
|
|
|
func newIterator() *iterator {
|
|
return itPool.Get().(*iterator)
|
|
}
|
|
|
|
func freeIterator(i *iterator) {
|
|
itPool.Put(i)
|
|
}
|
|
|
|
type iterator struct {
|
|
resBuf []*Change
|
|
stack []*Change
|
|
f func(c *Change) bool
|
|
}
|
|
|
|
func (i *iterator) iterateSkip(start *Change, skipBefore *Change, f func(c *Change) (isContinue bool)) {
|
|
skipping := true
|
|
i.iterate(start, func(c *Change) (isContinue bool) {
|
|
if skipping && c != skipBefore {
|
|
return true
|
|
}
|
|
skipping = false
|
|
return f(c)
|
|
})
|
|
}
|
|
|
|
func (i *iterator) topSort(start *Change) {
|
|
stack := i.stack
|
|
stack = append(stack, start)
|
|
|
|
for len(stack) > 0 {
|
|
ch := stack[len(stack)-1]
|
|
stack = stack[:len(stack)-1]
|
|
|
|
// here we visit the change second time to add it to results
|
|
// all next changes at this point were visited
|
|
if ch.branchesFinished {
|
|
i.resBuf = append(i.resBuf, ch)
|
|
ch.branchesFinished = false
|
|
continue
|
|
}
|
|
|
|
if ch.visited {
|
|
continue
|
|
}
|
|
|
|
// put the change again into stack, so we can add it to results
|
|
// after all the next changes
|
|
stack = append(stack, ch)
|
|
ch.visited = true
|
|
ch.branchesFinished = true
|
|
|
|
for j := 0; j < len(ch.Next); j++ {
|
|
if !ch.Next[j].visited {
|
|
stack = append(stack, ch.Next[j])
|
|
}
|
|
}
|
|
}
|
|
for _, ch := range i.resBuf {
|
|
ch.visited = false
|
|
}
|
|
}
|
|
|
|
func (i *iterator) iterate(start *Change, f func(c *Change) (isContinue bool)) {
|
|
if start == nil {
|
|
return
|
|
}
|
|
// reset
|
|
i.resBuf = i.resBuf[:0]
|
|
i.stack = i.stack[:0]
|
|
i.f = f
|
|
|
|
i.topSort(start)
|
|
for idx := len(i.resBuf) - 1; idx >= 0; idx-- {
|
|
if !f(i.resBuf[idx]) {
|
|
return
|
|
}
|
|
}
|
|
}
|