• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

mlange-42 / ark / 13639891374

03 Mar 2025 08:33PM CUT coverage: 98.504%. Remained the same
13639891374

Pull #117

github

web-flow
Merge f2543287f into 14baa6b40
Pull Request #117: Extend filter documentation

5730 of 5817 relevant lines covered (98.5%)

34452.31 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

94.96
/ecs/table.go
1
package ecs
2

3
import (
4
        "fmt"
5
        "math"
6
        "unsafe"
7
)
8

9
type tableID uint32
10

11
// maxTableID is used as table ID for unused entities.
12
const maxTableID = math.MaxUint32
13

14
type table struct {
15
        id          tableID
16
        archetype   archetypeID
17
        components  []int16      // mapping from component IDs to column indices
18
        entities    column       // column for entities
19
        ids         []ID         // components IDs in the same order as in the archetype
20
        columns     []column     // columns in dense order
21
        relationIDs []RelationID // all relation IDs and targets of the table
22

23
        zeroValue   []byte         // zero value with the size of the largest item type, for fast zeroing
24
        zeroPointer unsafe.Pointer // pointer to the zero value, for fast zeroing
25
}
26

27
func newTable(id tableID, archetype archetypeID, capacity uint32, reg *componentRegistry,
28
        ids []ID, componentsMap []int16, isRelation []bool, targets []Entity, relationIDs []RelationID) table {
656✔
29

656✔
30
        entities := newColumn(entityType, false, Entity{}, capacity)
656✔
31
        columns := make([]column, len(ids))
656✔
32

656✔
33
        var maxSize uintptr = entitySize
656✔
34
        for i, id := range ids {
2,370✔
35
                columns[i] = newColumn(reg.Types[id.id], isRelation[i], targets[i], capacity)
1,714✔
36
                if columns[i].itemSize > maxSize {
2,158✔
37
                        maxSize = columns[i].itemSize
444✔
38
                }
444✔
39
        }
40
        var zeroValue []byte
656✔
41
        var zeroPointer unsafe.Pointer
656✔
42
        if maxSize > 0 {
1,312✔
43
                zeroValue = make([]byte, maxSize)
656✔
44
                zeroPointer = unsafe.Pointer(&zeroValue[0])
656✔
45
        }
656✔
46

47
        return table{
656✔
48
                id:          id,
656✔
49
                archetype:   archetype,
656✔
50
                components:  componentsMap,
656✔
51
                entities:    entities,
656✔
52
                ids:         ids,
656✔
53
                columns:     columns,
656✔
54
                zeroValue:   zeroValue,
656✔
55
                zeroPointer: zeroPointer,
656✔
56
                relationIDs: relationIDs,
656✔
57
        }
656✔
58
}
59

60
func (t *table) recycle(targets []Entity, relationIDs []RelationID) {
2✔
61
        t.relationIDs = relationIDs
2✔
62
        for i := range t.columns {
5✔
63
                t.columns[i].target = targets[i]
3✔
64
        }
3✔
65
}
66

67
func (t *table) HasRelations() bool {
558✔
68
        return len(t.relationIDs) > 0
558✔
69
}
558✔
70

71
func (t *table) Add(entity Entity) uint32 {
501,744✔
72
        _, idx := t.entities.Add(unsafe.Pointer(&entity))
501,744✔
73

501,744✔
74
        for i := range t.columns {
1,007,902✔
75
                t.columns[i].Alloc(1)
506,158✔
76
        }
506,158✔
77
        return idx
501,744✔
78
}
79

80
func (t *table) Get(component ID, index uintptr) unsafe.Pointer {
895✔
81
        return t.columns[t.components[component.id]].Get(index)
895✔
82
}
895✔
83

84
func (t *table) Has(component ID) bool {
58✔
85
        return t.components[component.id] >= 0
58✔
86
}
58✔
87

88
func (t *table) GetEntity(index uintptr) Entity {
2,467,228✔
89
        return *(*Entity)(t.entities.Get(index))
2,467,228✔
90
}
2,467,228✔
91

92
func (t *table) GetRelation(component ID) Entity {
359✔
93
        return t.columns[t.components[component.id]].target
359✔
94
}
359✔
95

96
func (t *table) GetColumn(component ID) *column {
2,499✔
97
        return &t.columns[t.components[component.id]]
2,499✔
98
}
2,499✔
99

100
func (t *table) GetEntities(component ID) *column {
×
101
        return &t.entities
×
102
}
×
103

104
func (t *table) Set(component ID, index uint32, comp unsafe.Pointer) {
511,265✔
105
        t.columns[t.components[component.id]].Set(index, comp)
511,265✔
106
}
511,265✔
107

108
func (t *table) SetEntity(index uint32, entity Entity) {
2,014✔
109
        t.entities.Set(index, unsafe.Pointer(&entity))
2,014✔
110
}
2,014✔
111

112
// Alloc allocates memory for the given number of entities.
113
func (t *table) Alloc(n uint32) {
134✔
114
        t.entities.Alloc(n)
134✔
115
        for i := range t.columns {
433✔
116
                t.columns[i].Alloc(n)
299✔
117
        }
299✔
118
}
119

120
func (t *table) Remove(index uint32) bool {
498,860✔
121
        swapped := t.entities.Remove(index, nil)
498,860✔
122
        for i := range t.columns {
999,513✔
123
                t.columns[i].Remove(index, t.zeroPointer)
500,653✔
124
        }
500,653✔
125
        return swapped
498,860✔
126
}
127

128
func (t *table) Reset() {
184✔
129
        t.entities.Reset(nil)
184✔
130
        for c := range t.columns {
771✔
131
                t.columns[c].Reset(t.zeroPointer)
587✔
132
        }
587✔
133
}
134

135
func (t *table) AddAll(other *table, count uint32) {
10✔
136
        t.entities.AddAll(&other.entities, count)
10✔
137
        for c := range t.columns {
51✔
138
                t.columns[c].AddAll(&other.columns[c], count)
41✔
139
        }
41✔
140
}
141

142
func (t *table) AddAllEntities(other *table, count uint32, allocColumns bool) {
160✔
143
        t.entities.AddAll(&other.entities, count)
160✔
144
        if allocColumns {
320✔
145
                for c := range t.columns {
912✔
146
                        t.columns[c].Alloc(uint32(count))
752✔
147
                }
752✔
148
        }
149
}
150

151
func (t *table) MatchesExact(relations []RelationID) bool {
606✔
152
        if len(relations) != len(t.relationIDs) {
606✔
153
                panic("relation targets must be fully specified")
×
154
        }
155
        for _, rel := range relations {
1,270✔
156
                index := t.components[rel.component.id]
664✔
157
                if !t.columns[index].isRelation {
664✔
158
                        panic(fmt.Sprintf("component %d is not a relation component", rel.component.id))
×
159
                }
160
                //if rel.target == wildcard {
161
                //        panic("relation targets must be fully specified, no wildcard allowed")
162
                //}
163
                if rel.target != t.columns[index].target {
685✔
164
                        return false
21✔
165
                }
21✔
166
        }
167
        return true
585✔
168
}
169

170
func (t *table) Matches(relations []RelationID) bool {
196✔
171
        if len(relations) == 0 || !t.HasRelations() {
315✔
172
                return true
119✔
173
        }
119✔
174
        for _, rel := range relations {
156✔
175
                if rel.target == wildcard {
79✔
176
                        continue
×
177
                }
178
                if rel.target != t.columns[t.components[rel.component.id]].target {
97✔
179
                        return false
18✔
180
                }
18✔
181
        }
182
        return true
59✔
183
}
184

185
func (t *table) Len() int {
2,206✔
186
        return t.entities.Len()
2,206✔
187
}
2,206✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc