/
note.go
102 lines (97 loc) 路 2.81 KB
/
note.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
package strategies
import (
"context"
"fmt"
"github.com/1pkg/gopium/collections"
"github.com/1pkg/gopium/gopium"
)
// list of note presets
var (
fnotedoc = note{doc: true, field: true}
fnotecom = note{doc: false, field: true}
stnotedoc = note{doc: true, field: false}
stnotecom = note{doc: false, field: false}
)
// note defines strategy implementation
// that adds size doc or comment annotation
// for each structure field
// and aggregated size annotation for structure
type note struct {
doc bool `gopium:"filter_pads,memory_pack,cache_rounding_cpu_l1_discrete,struct_annotate_comment,add_tag_group_force"`
field bool `gopium:"filter_pads,memory_pack,cache_rounding_cpu_l1_discrete,struct_annotate_comment,add_tag_group_force"`
} // struct size: 2 bytes; struct align: 1 bytes; struct aligned size: 2 bytes; struct ptr scan size: 0 bytes; - 馃尯 gopium @1pkg
// Apply note implementation
func (stg note) Apply(ctx context.Context, o gopium.Struct) (gopium.Struct, error) {
// copy original structure to result
r := collections.CopyStruct(o)
// preset defaults
var size, alsize, align, aptr, prevptr int64 = 0, 0, 1, 0, 0
// prepare fields slice
if flen := len(r.Fields); flen > 0 {
// note each field with size comment
rfields := make([]gopium.Field, 0, flen)
collections.WalkStruct(r, 0, func(pad int64, fields ...gopium.Field) {
// add pad to aligned size
alsize += pad
for _, f := range fields {
// note only in field mode
if stg.field {
// create note comment
note := fmt.Sprintf(
"// field size: %d bytes; field align: %d bytes; field ptr: %d bytes; - %s",
f.Size,
f.Align,
f.Ptr,
gopium.STAMP,
)
if stg.doc {
f.Doc = append(f.Doc, note)
} else {
f.Comment = append(f.Comment, note)
}
}
// add field size to both sizes
size += f.Size
alsize += f.Size
// for pointer data track prev fields
// if current field has pointer data
// then add prev fields size + ptr size
// otherwise track prev fields further
if f.Ptr > 0 {
aptr += prevptr + f.Ptr
prevptr = f.Size - f.Ptr
} else {
prevptr += f.Size
}
// update struct align size
// if field align size is bigger
if f.Align > align {
align = f.Align
}
// append field to result
rfields = append(rfields, f)
}
})
// update result fields
r.Fields = rfields
}
// note structure with size comment
// note only in non field mode
if !stg.field {
// create note comment
note := fmt.Sprintf(
"// struct size: %d bytes; struct align: %d bytes; struct aligned size: %d bytes; struct ptr scan size: %d bytes; - %s",
size,
align,
alsize,
aptr,
gopium.STAMP,
)
if stg.doc {
r.Doc = append(r.Doc, note)
} else {
r.Comment = append(r.Comment, note)
}
}
return r, ctx.Err()
}