github.com/robotn/xgb@v0.0.0-20190912153532-2cb92d044934/xgbgen/aligngap.go (about) 1 package main 2 3 import ( 4 "fmt" 5 "os" 6 ) 7 8 func (p *Protocol) AddAlignGaps() { 9 for i := range p.Imports { 10 p.Imports[i].AddAlignGaps() 11 } 12 for i := range p.Types { 13 switch t := p.Types[i].(type) { 14 case *Struct: 15 t.Fields = addAlignGapsToFields(t.xmlName, t.Fields) 16 case *Event: 17 t.Fields = addAlignGapsToFields(t.xmlName, t.Fields) 18 case *Error: 19 t.Fields = addAlignGapsToFields(t.xmlName, t.Fields) 20 } 21 } 22 for i := range p.Requests { 23 p.Requests[i].Fields = addAlignGapsToFields( 24 p.Requests[i].xmlName, p.Requests[i].Fields) 25 if p.Requests[i].Reply != nil { 26 p.Requests[i].Reply.Fields = addAlignGapsToFields( 27 p.Requests[i].xmlName, p.Requests[i].Reply.Fields) 28 } 29 } 30 } 31 32 func addAlignGapsToFields(name string, fields []Field) []Field { 33 var i int 34 for i = 0; i < len(fields); i++ { 35 if _, ok := fields[i].(*ListField); ok { 36 break 37 } 38 } 39 if i >= len(fields) { 40 return fields 41 } 42 43 r := make([]Field, 0, len(fields)+2) 44 r = append(r, fields[:i]...) 45 46 r = append(r, fields[i]) 47 for i = i + 1; i < len(fields); i++ { 48 switch f := fields[i].(type) { 49 case *ListField: 50 // ok, add padding 51 sz := xcbSizeOfType(f.Type) 52 switch { 53 case sz == 1: 54 // nothing 55 case sz == 2: 56 r = append(r, &PadField{0, 2}) 57 case sz == 3: 58 panic(fmt.Errorf("Alignment is not a power of 2")) 59 case sz >= 4: 60 r = append(r, &PadField{0, 4}) 61 } 62 case *LocalField: 63 // nothing 64 default: 65 fmt.Fprintf(os.Stderr, 66 "Can't add alignment gaps, mix of list and non-list "+ 67 "fields: %s\n", name) 68 return fields 69 } 70 r = append(r, fields[i]) 71 } 72 return r 73 } 74 75 func xcbSizeOfField(fld Field) int { 76 switch f := fld.(type) { 77 case *PadField: 78 return int(f.Bytes) 79 case *SingleField: 80 return xcbSizeOfType(f.Type) 81 case *ListField: 82 return 0 83 case *ExprField: 84 return xcbSizeOfType(f.Type) 85 case *ValueField: 86 return xcbSizeOfType(f.MaskType) 87 case *SwitchField: 88 return 0 89 default: 90 return 0 91 } 92 } 93 94 func xcbSizeOfType(typ Type) int { 95 switch t := typ.(type) { 96 case *Resource: 97 return 4 98 case *TypeDef: 99 return t.Size().Eval() 100 case *Base: 101 return t.Size().Eval() 102 case *Struct: 103 sz := 0 104 for i := range t.Fields { 105 sz += xcbSizeOfField(t.Fields[i]) 106 } 107 return sz 108 case *Union: 109 sz := 0 110 for i := range t.Fields { 111 csz := xcbSizeOfField(t.Fields[i]) 112 if csz > sz { 113 sz = csz 114 } 115 } 116 return sz 117 default: 118 return 0 119 } 120 }