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

mlange-42 / ark / 13638010820

03 Mar 2025 06:39PM CUT coverage: 98.153% (+0.4%) from 97.712%
13638010820

Pull #114

github

web-flow
Merge 707ec851b into 0dcd540e6
Pull Request #114: Filter caching

529 of 537 new or added lines in 9 files covered. (98.51%)

2 existing lines in 1 file now uncovered.

5687 of 5794 relevant lines covered (98.15%)

33949.98 hits per line

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

96.33
/ecs/column.go
1
package ecs
2

3
import (
4
        "reflect"
5
        "unsafe"
6
)
7

8
// column storage for components in an archetype.
9
type column struct {
10
        data       reflect.Value  // data buffer
11
        pointer    unsafe.Pointer // pointer to the first element
12
        isRelation bool           // whether this column is for a relation component
13
        target     Entity         // target entity if for a relation component
14
        itemSize   uintptr        // memory size of items
15
        len        uint32         // number of items
16
}
17

18
// newColumn creates a new column for a given type and capacity.
19
func newColumn(tp reflect.Type, isRelation bool, target Entity, capacity uint32) column {
2,373✔
20
        // TODO: should be use a slice instead of an array here?
2,373✔
21
        data := reflect.New(reflect.ArrayOf(int(capacity), tp)).Elem()
2,373✔
22
        pointer := data.Addr().UnsafePointer()
2,373✔
23

2,373✔
24
        return column{
2,373✔
25
                data:       data,
2,373✔
26
                pointer:    pointer,
2,373✔
27
                itemSize:   sizeOf(tp),
2,373✔
28
                isRelation: isRelation,
2,373✔
29
                target:     target,
2,373✔
30
                len:        0,
2,373✔
31
        }
2,373✔
32
}
2,373✔
33

34
// Len returns the number of components in the column.
35
func (c *column) Len() int {
994,277✔
36
        return int(c.len)
994,277✔
37
}
994,277✔
38

39
// Cap returns the current capacity of the column.
40
func (c *column) Cap() int {
990,810✔
41
        return c.data.Cap()
990,810✔
42
}
990,810✔
43

44
// Get returns a pointer to the component at the given index.
45
func (c *column) Get(index uintptr) unsafe.Pointer {
4,875,655✔
46
        return unsafe.Add(c.pointer, index*c.itemSize)
4,875,655✔
47
}
4,875,655✔
48

49
// Add adds a component to the column.
50
func (c *column) Add(comp unsafe.Pointer) (unsafe.Pointer, uint32) {
492,508✔
51
        c.Extend(1)
492,508✔
52
        c.len++
492,508✔
53
        return c.Set(c.len-1, comp), c.len - 1
492,508✔
54
}
492,508✔
55

56
// Alloc allocates memory for the given number of components.
57
func (c *column) Alloc(n uint32) {
498,296✔
58
        c.Extend(n)
498,296✔
59
        c.len += n
498,296✔
60
}
498,296✔
61

62
func (c *column) AddAll(other *column, count uint32) {
211✔
63
        oldLen := c.len
211✔
64
        c.Alloc(count)
211✔
65
        src := other.Get(0)
211✔
66
        dst := c.Get(uintptr(oldLen))
211✔
67
        copyPtr(src, dst, c.itemSize*uintptr(count))
211✔
68
}
211✔
69

70
func (c *column) SetLast(other *column, count uint32) {
320✔
71
        start := c.len - count
320✔
72
        src := other.Get(0)
320✔
73
        dst := c.Get(uintptr(start))
320✔
74
        copyPtr(src, dst, c.itemSize*uintptr(count))
320✔
75
}
320✔
76

77
// Set overwrites the component at the given index.
78
func (c *column) Set(index uint32, comp unsafe.Pointer) unsafe.Pointer {
996,531✔
79
        dst := c.Get(uintptr(index))
996,531✔
80
        if c.itemSize == 0 {
997,665✔
81
                return dst
1,134✔
82
        }
1,134✔
83

84
        copyPtr(comp, dst, uintptr(c.itemSize))
995,397✔
85
        return dst
995,397✔
86
}
87

88
// Remove swap-removes the component at the given index.
89
// Returns whether a swap was necessary.
90
func (c *column) Remove(index uint32, zero unsafe.Pointer) bool {
983,897✔
91
        lastIndex := uintptr(c.len - 1)
983,897✔
92
        swapped := index != uint32(lastIndex)
983,897✔
93

983,897✔
94
        if swapped && c.itemSize != 0 {
1,962,758✔
95
                src := unsafe.Add(c.pointer, lastIndex*c.itemSize)
978,861✔
96
                dst := unsafe.Add(c.pointer, uintptr(index)*c.itemSize)
978,861✔
97
                copyPtr(src, dst, uintptr(c.itemSize))
978,861✔
98
        }
978,861✔
99
        c.len--
983,897✔
100
        if zero != nil {
1,476,742✔
101
                c.Zero(lastIndex, zero)
492,845✔
102
        }
492,845✔
103
        return swapped
983,897✔
104
}
105

106
// Extend the column to be able to store the given number of additional components.
107
// Has no effect of the column's capacity is already sufficient.
108
// If the capacity needs to be increased, it will be doubled until it is sufficient.
109
func (c *column) Extend(by uint32) {
990,804✔
110
        required := c.Len() + int(by)
990,804✔
111
        cap := c.Cap()
990,804✔
112
        if cap >= required {
1,979,330✔
113
                return
988,526✔
114
        }
988,526✔
115
        for cap < required {
4,644✔
116
                cap *= 2
2,366✔
117
        }
2,366✔
118
        old := c.data
2,278✔
119
        c.data = reflect.New(reflect.ArrayOf(cap, old.Type().Elem())).Elem()
2,278✔
120
        c.pointer = c.data.Addr().UnsafePointer()
2,278✔
121
        reflect.Copy(c.data, old)
2,278✔
122
}
123

124
// Zero resets the memory at the given index.
125
func (c *column) Zero(index uintptr, zero unsafe.Pointer) {
492,845✔
126
        if c.itemSize == 0 {
493,064✔
127
                return
219✔
128
        }
219✔
129
        dst := unsafe.Add(c.pointer, index*c.itemSize)
492,626✔
130
        copyPtr(zero, dst, uintptr(c.itemSize))
492,626✔
131
}
132

133
// Zero resets a block of storage in one buffer.
134
func (c *column) ZeroRange(start, len uint32, zero unsafe.Pointer) {
587✔
135
        size := uint32(c.itemSize)
587✔
136
        if size == 0 {
604✔
137
                return
17✔
138
        }
17✔
139
        var i uint32
570✔
140
        for i = 0; i < len; i++ {
7,713✔
141
                dst := unsafe.Add(c.pointer, (i+start)*size)
7,143✔
142
                copyPtr(zero, dst, c.itemSize)
7,143✔
143
        }
7,143✔
144
}
145

146
func (c *column) Reset(zero unsafe.Pointer) {
771✔
147
        len := c.len
771✔
148
        if c.len == 0 {
771✔
UNCOV
149
                return
×
UNCOV
150
        }
×
151
        c.len = 0
771✔
152
        if zero == nil {
955✔
153
                return
184✔
154
        }
184✔
155
        if len <= 64 { // A coarse estimate where manually zeroing is faster
1,174✔
156
                c.ZeroRange(0, len, zero)
587✔
157
        } else {
587✔
158
                c.data.SetZero()
×
159
        }
×
160
}
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