X-Git-Url: https://git.josue.xyz/?a=blobdiff_plain;f=.config%2Fcoc%2Fextensions%2Fcoc-go-data%2Ftools%2Fpkg%2Fmod%2Fhonnef.co%2Fgo%2Ftools%40v0.0.1-2020.1.5%2Fcmd%2Fstructlayout-optimize%2Fmain.go;fp=.config%2Fcoc%2Fextensions%2Fcoc-go-data%2Ftools%2Fpkg%2Fmod%2Fhonnef.co%2Fgo%2Ftools%40v0.0.1-2020.1.5%2Fcmd%2Fstructlayout-optimize%2Fmain.go;h=dd9c1f3b50960d4c021255827cc30c2397af3649;hb=4d07c77cf4d78cab8639e13ddc3c22495e585b0b;hp=0000000000000000000000000000000000000000;hpb=b3950616b54221c40a7dab9099bda675007e5b6e;p=dotfiles%2F.git diff --git a/.config/coc/extensions/coc-go-data/tools/pkg/mod/honnef.co/go/tools@v0.0.1-2020.1.5/cmd/structlayout-optimize/main.go b/.config/coc/extensions/coc-go-data/tools/pkg/mod/honnef.co/go/tools@v0.0.1-2020.1.5/cmd/structlayout-optimize/main.go new file mode 100644 index 00000000..dd9c1f3b --- /dev/null +++ b/.config/coc/extensions/coc-go-data/tools/pkg/mod/honnef.co/go/tools@v0.0.1-2020.1.5/cmd/structlayout-optimize/main.go @@ -0,0 +1,205 @@ +// structlayout-optimize reorders struct fields to minimize the amount +// of padding. +package main + +import ( + "encoding/json" + "flag" + "fmt" + "log" + "os" + "sort" + "strings" + + st "honnef.co/go/tools/structlayout" + "honnef.co/go/tools/version" +) + +var ( + fJSON bool + fRecurse bool + fVersion bool +) + +func init() { + flag.BoolVar(&fJSON, "json", false, "Format data as JSON") + flag.BoolVar(&fRecurse, "r", false, "Break up structs and reorder their fields freely") + flag.BoolVar(&fVersion, "version", false, "Print version and exit") +} + +func main() { + log.SetFlags(0) + flag.Parse() + + if fVersion { + version.Print() + os.Exit(0) + } + + var in []st.Field + if err := json.NewDecoder(os.Stdin).Decode(&in); err != nil { + log.Fatal(err) + } + if len(in) == 0 { + return + } + if !fRecurse { + in = combine(in) + } + var fields []st.Field + for _, field := range in { + if field.IsPadding { + continue + } + fields = append(fields, field) + } + optimize(fields) + fields = pad(fields) + + if fJSON { + json.NewEncoder(os.Stdout).Encode(fields) + } else { + for _, field := range fields { + fmt.Println(field) + } + } +} + +func combine(fields []st.Field) []st.Field { + new := st.Field{} + cur := "" + var out []st.Field + wasPad := true + for _, field := range fields { + var prefix string + if field.IsPadding { + wasPad = true + continue + } + p := strings.Split(field.Name, ".") + prefix = strings.Join(p[:2], ".") + if field.Align > new.Align { + new.Align = field.Align + } + if !wasPad { + new.End = field.Start + new.Size = new.End - new.Start + } + if prefix != cur { + if cur != "" { + out = append(out, new) + } + cur = prefix + new = field + new.Name = prefix + } else { + new.Type = "struct" + } + wasPad = false + } + new.Size = new.End - new.Start + out = append(out, new) + return out +} + +func optimize(fields []st.Field) { + sort.Sort(&byAlignAndSize{fields}) +} + +func pad(fields []st.Field) []st.Field { + if len(fields) == 0 { + return nil + } + var out []st.Field + pos := int64(0) + offsets := offsetsof(fields) + alignment := int64(1) + for i, field := range fields { + if field.Align > alignment { + alignment = field.Align + } + if offsets[i] > pos { + padding := offsets[i] - pos + out = append(out, st.Field{ + IsPadding: true, + Start: pos, + End: pos + padding, + Size: padding, + }) + pos += padding + } + field.Start = pos + field.End = pos + field.Size + out = append(out, field) + pos += field.Size + } + sz := size(out) + pad := align(sz, alignment) - sz + if pad > 0 { + field := out[len(out)-1] + out = append(out, st.Field{ + IsPadding: true, + Start: field.End, + End: field.End + pad, + Size: pad, + }) + } + return out +} + +func size(fields []st.Field) int64 { + n := int64(0) + for _, field := range fields { + n += field.Size + } + return n +} + +type byAlignAndSize struct { + fields []st.Field +} + +func (s *byAlignAndSize) Len() int { return len(s.fields) } +func (s *byAlignAndSize) Swap(i, j int) { + s.fields[i], s.fields[j] = s.fields[j], s.fields[i] +} + +func (s *byAlignAndSize) Less(i, j int) bool { + // Place zero sized objects before non-zero sized objects. + if s.fields[i].Size == 0 && s.fields[j].Size != 0 { + return true + } + if s.fields[j].Size == 0 && s.fields[i].Size != 0 { + return false + } + + // Next, place more tightly aligned objects before less tightly aligned objects. + if s.fields[i].Align != s.fields[j].Align { + return s.fields[i].Align > s.fields[j].Align + } + + // Lastly, order by size. + if s.fields[i].Size != s.fields[j].Size { + return s.fields[i].Size > s.fields[j].Size + } + + return false +} + +func offsetsof(fields []st.Field) []int64 { + offsets := make([]int64, len(fields)) + var o int64 + for i, f := range fields { + a := f.Align + o = align(o, a) + offsets[i] = o + o += f.Size + } + return offsets +} + +// align returns the smallest y >= x such that y % a == 0. +func align(x, a int64) int64 { + y := x + a - 1 + return y - y%a +}