github.com/BurntSushi/xgb@v0.0.0-20210121224620-deaf085860bc/xgbgen/xml_fields.go (about)

     1  package main
     2  
     3  import (
     4  	"encoding/xml"
     5  	"log"
     6  )
     7  
     8  type XMLField struct {
     9  	XMLName xml.Name
    10  
    11  	// For 'pad' element
    12  	Bytes uint `xml:"bytes,attr"`
    13  
    14  	// For 'field', 'list', 'localfield', 'exprfield' and 'switch' elements.
    15  	Name string `xml:"name,attr"`
    16  
    17  	// For 'field', 'list', 'localfield', and 'exprfield' elements.
    18  	Type string `xml:"type,attr"`
    19  
    20  	// For 'list', 'exprfield' and 'switch' elements.
    21  	Expr *XMLExpression `xml:",any"`
    22  
    23  	// For 'valueparm' element.
    24  	ValueMaskType string `xml:"value-mask-type,attr"`
    25  	ValueMaskName string `xml:"value-mask-name,attr"`
    26  	ValueListName string `xml:"value-list-name,attr"`
    27  
    28  	// For 'switch' element.
    29  	Bitcases []*XMLBitcase `xml:"bitcase"`
    30  
    31  	// I don't know which elements these are for. The documentation is vague.
    32  	// They also seem to be completely optional.
    33  	OptEnum    string `xml:"enum,attr"`
    34  	OptMask    string `xml:"mask,attr"`
    35  	OptAltEnum string `xml:"altenum,attr"`
    36  }
    37  
    38  // Bitcase represents a single expression followed by any number of fields.
    39  // Namely, if the switch's expression (all bitcases are inside a switch),
    40  // and'd with the bitcase's expression is equal to the bitcase expression,
    41  // then the fields should be included in its parent structure.
    42  // Note that since a bitcase is unique in that expressions and fields are
    43  // siblings, we must exhaustively search for one of them. Essentially,
    44  // it's the closest thing to a Union I can get to in Go without interfaces.
    45  // Would an '<expression>' tag have been too much to ask? :-(
    46  type XMLBitcase struct {
    47  	Fields []*XMLField `xml:",any"`
    48  
    49  	// All the different expressions.
    50  	// When it comes time to choose one, use the 'Expr' method.
    51  	ExprOp    *XMLExpression `xml:"op"`
    52  	ExprUnOp  *XMLExpression `xml:"unop"`
    53  	ExprField *XMLExpression `xml:"fieldref"`
    54  	ExprValue *XMLExpression `xml:"value"`
    55  	ExprBit   *XMLExpression `xml:"bit"`
    56  	ExprEnum  *XMLExpression `xml:"enumref"`
    57  	ExprSum   *XMLExpression `xml:"sumof"`
    58  	ExprPop   *XMLExpression `xml:"popcount"`
    59  }
    60  
    61  // Expr chooses the only non-nil Expr* field from Bitcase.
    62  // Panic if there is more than one non-nil expression.
    63  func (b *XMLBitcase) Expr() *XMLExpression {
    64  	choices := []*XMLExpression{
    65  		b.ExprOp, b.ExprUnOp, b.ExprField, b.ExprValue,
    66  		b.ExprBit, b.ExprEnum, b.ExprSum, b.ExprPop,
    67  	}
    68  
    69  	var choice *XMLExpression = nil
    70  	numNonNil := 0
    71  	for _, c := range choices {
    72  		if c != nil {
    73  			numNonNil++
    74  			choice = c
    75  		}
    76  	}
    77  
    78  	if choice == nil {
    79  		log.Panicf("No top level expression found in a bitcase.")
    80  	}
    81  	if numNonNil > 1 {
    82  		log.Panicf("More than one top-level expression was found in a bitcase.")
    83  	}
    84  	return choice
    85  }