/
fixed.go
135 lines (112 loc) · 3.63 KB
/
fixed.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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
package base
import (
"bytes"
"fmt"
)
// FixedAttributeGroups contain a particular number of rows of
// a particular number of Attributes, all of a given type.
type FixedAttributeGroup struct {
threadNo uint32
parent DataGrid
attributes []Attribute
size int
alloc [][]byte
maxRow int
}
func (f *FixedAttributeGroup) String() string {
if len(f.alloc) > 1 {
return fmt.Sprintf("FixedAttributeGroup(%d attributes\n thread: %d\n size: %d\n)", len(f.attributes), f.threadNo, f.size)
}
return fmt.Sprintf("FixedAttributeGroup(%d attributes\n thread: %d\n size: %d\n %d \n)", len(f.attributes), f.threadNo, f.size, f.alloc[0][0:60])
}
// RowSize returns the size of each row in bytes
func (f *FixedAttributeGroup) RowSize() int {
return len(f.attributes) * f.size
}
// Attributes returns a slice of Attributes in this FixedAttributeGroup
func (f *FixedAttributeGroup) Attributes() []Attribute {
return f.attributes
}
// AddAttribute adds an attribute to this FixedAttributeGroup
func (f *FixedAttributeGroup) AddAttribute(a Attribute) error {
f.attributes = append(f.attributes, a)
return nil
}
// getThreadNo returns the ThreadNo assigned to this FixedAttributeGroup
func (f *FixedAttributeGroup) getThreadNo() uint32 {
return f.threadNo
}
// addStorage appends the given storage reference to this FixedAttributeGroup
func (f *FixedAttributeGroup) addStorage(a []byte) {
f.alloc = append(f.alloc, a)
}
// Storage returns a slice of FixedAttributeGroupStorageRefs which can
// be used to access the memory in this pond.
func (f *FixedAttributeGroup) Storage() []AttributeGroupStorageRef {
ret := make([]AttributeGroupStorageRef, len(f.alloc))
rowSize := f.RowSize()
for i, b := range f.alloc {
ret[i] = AttributeGroupStorageRef{b, len(b) / rowSize}
}
return ret
}
func (f *FixedAttributeGroup) resolveBlock(col int, row int) (int, int) {
if len(f.alloc) == 0 {
panic("No blocks to resolve")
}
// Find where in the pond the byte is
byteOffset := row*f.RowSize() + col*f.size
return f.resolveBlockFromByteOffset(byteOffset, f.RowSize())
}
func (f *FixedAttributeGroup) resolveBlockFromByteOffset(byteOffset, rowSize int) (int, int) {
curOffset := 0
curBlock := 0
blockOffset := 0
for {
if curBlock >= len(f.alloc) {
panic("Don't have enough blocks to fulfill")
}
// Rows are not allowed to span blocks
blockAdd := len(f.alloc[curBlock])
blockAdd -= blockAdd % rowSize
// Case 1: we need to skip this allocation
if curOffset+blockAdd < byteOffset {
curOffset += blockAdd
curBlock++
} else {
blockOffset = byteOffset - curOffset
break
}
}
return curBlock, blockOffset
}
func (f *FixedAttributeGroup) set(col int, row int, val []byte) {
// Double-check the length
if len(val) != f.size {
panic(fmt.Sprintf("Tried to call set() with %d bytes, should be %d", len(val), f.size))
}
// Find where in the pond the byte is
curBlock, blockOffset := f.resolveBlock(col, row)
// Copy the value in
copied := copy(f.alloc[curBlock][blockOffset:], val)
if copied != f.size {
panic(fmt.Sprintf("set() terminated by only copying %d bytes into the current block (should be %d). Check EDF allocation", copied, f.size))
}
row++
if row > f.maxRow {
f.maxRow = row
}
}
func (f *FixedAttributeGroup) get(col int, row int) []byte {
curBlock, blockOffset := f.resolveBlock(col, row)
return f.alloc[curBlock][blockOffset : blockOffset+f.size]
}
func (f *FixedAttributeGroup) appendToRowBuf(row int, buffer *bytes.Buffer) {
for i, a := range f.attributes {
postfix := " "
if i == len(f.attributes)-1 {
postfix = ""
}
buffer.WriteString(fmt.Sprintf("%s%s", a.GetStringFromSysVal(f.get(i, row)), postfix))
}
}