github.com/robotn/xgb@v0.0.0-20190912153532-2cb92d044934/xgbgen/field.go (about)

     1  package main
     2  
     3  import (
     4  	"fmt"
     5  	"log"
     6  	"strings"
     7  )
     8  
     9  // Field corresponds to any field described in an XML protocol description
    10  // file. This includes struct fields, union fields, request fields,
    11  // reply fields and so on.
    12  // To make code generation easier, fields that have types are also stored.
    13  // Note that not all fields support all methods defined in this interface.
    14  // For instance, a padding field does not have a source name.
    15  type Field interface {
    16  	// Initialize sets up the source name of this field.
    17  	Initialize(p *Protocol)
    18  
    19  	// SrcName is the Go source name of this field.
    20  	SrcName() string
    21  
    22  	// XmlName is the name of this field from the XML file.
    23  	XmlName() string
    24  
    25  	// SrcType is the Go source type name of this field.
    26  	SrcType() string
    27  
    28  	// Size returns an expression that computes the size (in bytes)
    29  	// of this field.
    30  	Size() Size
    31  
    32  	// Define writes the Go code to declare this field (in a struct definition).
    33  	Define(c *Context)
    34  
    35  	// Read writes the Go code to convert a byte slice to a Go value
    36  	// of this field.
    37  	// 'prefix' is the prefix of the name of the Go value.
    38  	Read(c *Context, prefix string)
    39  
    40  	// Write writes the Go code to convert a Go value to a byte slice of
    41  	// this field.
    42  	// 'prefix' is the prefix of the name of the Go value.
    43  	Write(c *Context, prefix string)
    44  }
    45  
    46  func (pad *PadField) Initialize(p *Protocol) {}
    47  
    48  // PadField represents any type of padding. It is omitted from
    49  // definitions, but is used in Read/Write to increment the buffer index.
    50  // It is also used in size calculation.
    51  type PadField struct {
    52  	Bytes uint
    53  	Align uint16
    54  }
    55  
    56  func (p *PadField) SrcName() string {
    57  	panic("illegal to take source name of a pad field")
    58  }
    59  
    60  func (p *PadField) XmlName() string {
    61  	panic("illegal to take XML name of a pad field")
    62  }
    63  
    64  func (f *PadField) SrcType() string {
    65  	panic("it is illegal to call SrcType on a PadField field")
    66  }
    67  
    68  func (p *PadField) Size() Size {
    69  	if p.Align > 0 {
    70  		return newFixedSize(uint(p.Align), false)
    71  	} else {
    72  		return newFixedSize(p.Bytes, true)
    73  	}
    74  }
    75  
    76  // SingleField represents most of the fields in an XML protocol description.
    77  // It corresponds to any single value.
    78  type SingleField struct {
    79  	srcName string
    80  	xmlName string
    81  	Type    Type
    82  }
    83  
    84  func (f *SingleField) Initialize(p *Protocol) {
    85  	f.srcName = SrcName(p, f.XmlName())
    86  	f.Type = f.Type.(*Translation).RealType(p)
    87  }
    88  
    89  func (f *SingleField) SrcName() string {
    90  	if f.srcName == "Bytes" {
    91  		return "Bytes_"
    92  	}
    93  	return f.srcName
    94  }
    95  
    96  func (f *SingleField) XmlName() string {
    97  	return f.xmlName
    98  }
    99  
   100  func (f *SingleField) SrcType() string {
   101  	return f.Type.SrcName()
   102  }
   103  
   104  func (f *SingleField) Size() Size {
   105  	return f.Type.Size()
   106  }
   107  
   108  // ListField represents a list of values.
   109  type ListField struct {
   110  	srcName    string
   111  	xmlName    string
   112  	Type       Type
   113  	LengthExpr Expression
   114  }
   115  
   116  func (f *ListField) SrcName() string {
   117  	return f.srcName
   118  }
   119  
   120  func (f *ListField) XmlName() string {
   121  	return f.xmlName
   122  }
   123  
   124  func (f *ListField) SrcType() string {
   125  	if strings.ToLower(f.Type.XmlName()) == "char" {
   126  		return fmt.Sprintf("string")
   127  	}
   128  	return fmt.Sprintf("[]%s", f.Type.SrcName())
   129  }
   130  
   131  // Length computes the *number* of values in a list.
   132  // If this ListField does not have any length expression, we throw our hands
   133  // up and simply compute the 'len' of the field name of this list.
   134  func (f *ListField) Length() Size {
   135  	if f.LengthExpr == nil {
   136  		return newExpressionSize(&Function{
   137  			Name: "len",
   138  			Expr: &FieldRef{
   139  				Name: f.SrcName(),
   140  			},
   141  		}, true)
   142  	}
   143  	return newExpressionSize(f.LengthExpr, true)
   144  }
   145  
   146  // Size computes the *size* of a list (in bytes).
   147  // It it typically a simple matter of multiplying the length of the list by
   148  // the size of the type of the list.
   149  // But if it's a list of struct where the struct has a list field, we use a
   150  // special function written in go_struct.go to compute the size (since the
   151  // size in this case can only be computed recursively).
   152  func (f *ListField) Size() Size {
   153  	elsz := f.Type.Size()
   154  	simpleLen := &Padding{
   155  		Expr: newBinaryOp("*", f.Length().Expression, elsz.Expression),
   156  	}
   157  
   158  	switch field := f.Type.(type) {
   159  	case *Struct:
   160  		if field.HasList() {
   161  			sizeFun := &Function{
   162  				Name: fmt.Sprintf("%sListSize", f.Type.SrcName()),
   163  				Expr: &FieldRef{Name: f.SrcName()},
   164  			}
   165  			return newExpressionSize(sizeFun, elsz.exact)
   166  		} else {
   167  			return newExpressionSize(simpleLen, elsz.exact)
   168  		}
   169  	case *Union:
   170  		return newExpressionSize(simpleLen, elsz.exact)
   171  	case *Base:
   172  		return newExpressionSize(simpleLen, elsz.exact)
   173  	case *Resource:
   174  		return newExpressionSize(simpleLen, elsz.exact)
   175  	case *TypeDef:
   176  		return newExpressionSize(simpleLen, elsz.exact)
   177  	default:
   178  		log.Panicf("Cannot compute list size with type '%T'.", f.Type)
   179  	}
   180  	panic("unreachable")
   181  }
   182  
   183  func (f *ListField) Initialize(p *Protocol) {
   184  	f.srcName = SrcName(p, f.XmlName())
   185  	f.Type = f.Type.(*Translation).RealType(p)
   186  	if f.LengthExpr != nil {
   187  		f.LengthExpr.Initialize(p)
   188  	}
   189  }
   190  
   191  // LocalField is exactly the same as a regular SingleField, except it isn't
   192  // sent over the wire. (i.e., it's probably used to compute an ExprField).
   193  type LocalField struct {
   194  	*SingleField
   195  }
   196  
   197  // ExprField is a field that is not parameterized, but is computed from values
   198  // of other fields.
   199  type ExprField struct {
   200  	srcName string
   201  	xmlName string
   202  	Type    Type
   203  	Expr    Expression
   204  }
   205  
   206  func (f *ExprField) SrcName() string {
   207  	return f.srcName
   208  }
   209  
   210  func (f *ExprField) XmlName() string {
   211  	return f.xmlName
   212  }
   213  
   214  func (f *ExprField) SrcType() string {
   215  	return f.Type.SrcName()
   216  }
   217  
   218  func (f *ExprField) Size() Size {
   219  	return f.Type.Size()
   220  }
   221  
   222  func (f *ExprField) Initialize(p *Protocol) {
   223  	f.srcName = SrcName(p, f.XmlName())
   224  	f.Type = f.Type.(*Translation).RealType(p)
   225  	f.Expr.Initialize(p)
   226  }
   227  
   228  // ValueField represents two fields in one: a mask and a list of 4-byte
   229  // integers. The mask specifies which kinds of values are in the list.
   230  // (i.e., See ConfigureWindow, CreateWindow, ChangeWindowAttributes, etc.)
   231  type ValueField struct {
   232  	Parent   interface{}
   233  	MaskType Type
   234  	MaskName string
   235  	ListName string
   236  }
   237  
   238  func (f *ValueField) SrcName() string {
   239  	panic("it is illegal to call SrcName on a ValueField field")
   240  }
   241  
   242  func (f *ValueField) XmlName() string {
   243  	panic("it is illegal to call XmlName on a ValueField field")
   244  }
   245  
   246  func (f *ValueField) SrcType() string {
   247  	return f.MaskType.SrcName()
   248  }
   249  
   250  // Size computes the size in bytes of the combination of the mask and list
   251  // in this value field.
   252  // The expression to compute this looks complicated, but it's really just
   253  // the number of bits set in the mask multiplied 4 (and padded of course).
   254  func (f *ValueField) Size() Size {
   255  	maskSize := f.MaskType.Size()
   256  	listSize := newExpressionSize(&Function{
   257  		Name: "xgb.Pad",
   258  		Expr: &BinaryOp{
   259  			Op:    "*",
   260  			Expr1: &Value{v: 4},
   261  			Expr2: &PopCount{
   262  				Expr: &Function{
   263  					Name: "int",
   264  					Expr: &FieldRef{
   265  						Name: f.MaskName,
   266  					},
   267  				},
   268  			},
   269  		},
   270  	}, true)
   271  	return maskSize.Add(listSize)
   272  }
   273  
   274  func (f *ValueField) ListLength() Size {
   275  	return newExpressionSize(&PopCount{
   276  		Expr: &Function{
   277  			Name: "int",
   278  			Expr: &FieldRef{
   279  				Name: f.MaskName,
   280  			},
   281  		},
   282  	}, true)
   283  }
   284  
   285  func (f *ValueField) Initialize(p *Protocol) {
   286  	f.MaskType = f.MaskType.(*Translation).RealType(p)
   287  	f.MaskName = SrcName(p, f.MaskName)
   288  	f.ListName = SrcName(p, f.ListName)
   289  }
   290  
   291  // SwitchField represents a 'switch' element in the XML protocol description
   292  // file. It is not currently used. (i.e., it is XKB voodoo.)
   293  type SwitchField struct {
   294  	Name     string
   295  	Expr     Expression
   296  	Bitcases []*Bitcase
   297  }
   298  
   299  func (f *SwitchField) SrcName() string {
   300  	panic("it is illegal to call SrcName on a SwitchField field")
   301  }
   302  
   303  func (f *SwitchField) XmlName() string {
   304  	panic("it is illegal to call XmlName on a SwitchField field")
   305  }
   306  
   307  func (f *SwitchField) SrcType() string {
   308  	panic("it is illegal to call SrcType on a SwitchField field")
   309  }
   310  
   311  // XXX: This is a bit tricky. The size has to be represented as a non-concrete
   312  // expression that finds *which* bitcase fields are included, and sums the
   313  // sizes of those fields.
   314  func (f *SwitchField) Size() Size {
   315  	return newFixedSize(0, true)
   316  }
   317  
   318  func (f *SwitchField) Initialize(p *Protocol) {
   319  	f.Name = SrcName(p, f.Name)
   320  	f.Expr.Initialize(p)
   321  	for _, bitcase := range f.Bitcases {
   322  		bitcase.Expr.Initialize(p)
   323  		for _, field := range bitcase.Fields {
   324  			field.Initialize(p)
   325  		}
   326  	}
   327  }
   328  
   329  // Bitcase represents a single bitcase inside a switch expression.
   330  // It is not currently used. (i.e., it's XKB voodoo.)
   331  type Bitcase struct {
   332  	Fields []Field
   333  	Expr   Expression
   334  }