-
Notifications
You must be signed in to change notification settings - Fork 10
/
Copy pathshape_iter.go
119 lines (105 loc) · 2.32 KB
/
shape_iter.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
package ecs
import "unsafe"
type IShapeIterator[T any] interface {
Begin() *T
Val() *T
Next() *T
End() bool
}
type ShapeIter[T any] struct {
indices ShapeIndices
maxLen int
offset int
begin int
mainKeyIndex int
cur *T
}
func EmptyShapeIter[T any]() IShapeIterator[T] {
return &ShapeIter[T]{}
}
func NewShapeIterator[T any](indices ShapeIndices, mainKeyIndex int) IShapeIterator[T] {
iter := &ShapeIter[T]{
indices: indices,
maxLen: indices.containers[mainKeyIndex].Len(),
mainKeyIndex: mainKeyIndex,
offset: 0,
}
return iter
}
// TODO 热点
func (s *ShapeIter[T]) tryNext() *T {
skip := false
find := false
var p unsafe.Pointer
var ec *EmptyComponent
for i := s.offset; i < s.maxLen; i++ {
//TODO check if this is the best way to do this
p = s.indices.containers[s.mainKeyIndex].getPointerByIndex(int64(s.offset))
ec = (*EmptyComponent)(p)
if s.indices.readOnly[s.mainKeyIndex] {
*(**byte)(unsafe.Add(unsafe.Pointer(s.cur), s.indices.subOffset[s.mainKeyIndex])) = &(*(*byte)(p))
} else {
*(**byte)(unsafe.Add(unsafe.Pointer(s.cur), s.indices.subOffset[s.mainKeyIndex])) = (*byte)(p)
}
entity := ec.Owner()
skip = s.getSiblings(entity)
if !skip {
s.offset = i
find = true
break
}
}
if !find {
s.cur = nil
}
return s.cur
}
func (s *ShapeIter[T]) getSiblings(entity Entity) bool {
for i := 0; i < len(s.indices.subTypes); i++ {
if i == s.mainKeyIndex {
continue
}
subPointer := s.indices.containers[i].getPointerByEntity(entity)
if subPointer == nil {
return true
}
s.trans(i, subPointer)
}
return false
}
func (s *ShapeIter[T]) trans(i int, subPointer unsafe.Pointer) {
if s.indices.readOnly[i] {
*(**byte)(unsafe.Add(unsafe.Pointer(s.cur), s.indices.subOffset[i])) = &(*(*byte)(subPointer))
} else {
*(**byte)(unsafe.Add(unsafe.Pointer(s.cur), s.indices.subOffset[i])) = (*byte)(subPointer)
}
}
func (s *ShapeIter[T]) End() bool {
if s.cur == nil {
return true
}
return false
}
func (s *ShapeIter[T]) Begin() *T {
if s.maxLen != 0 {
s.offset = 0
s.cur = new(T)
s.tryNext()
}
return s.cur
}
func (s *ShapeIter[T]) Val() *T {
if s.cur == nil || !s.End() {
s.Begin()
}
return s.cur
}
func (s *ShapeIter[T]) Next() *T {
s.offset++
if !s.End() {
s.tryNext()
} else {
s.cur = nil
}
return s.cur
}