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

     1  package main
     2  
     3  import (
     4  	"fmt"
     5  	"log"
     6  )
     7  
     8  func (f *SingleField) Define(c *Context) {
     9  	c.Putln("%s %s", f.SrcName(), f.Type.SrcName())
    10  }
    11  
    12  func ReadSimpleSingleField(c *Context, name string, typ Type) {
    13  	switch t := typ.(type) {
    14  	case *Resource:
    15  		c.Putln("%s = %s(xgb.Get32(buf[b:]))", name, t.SrcName())
    16  	case *TypeDef:
    17  		switch t.Size().Eval() {
    18  		case 1:
    19  			c.Putln("%s = %s(buf[b])", name, t.SrcName())
    20  		case 2:
    21  			c.Putln("%s = %s(xgb.Get16(buf[b:]))", name, t.SrcName())
    22  		case 4:
    23  			c.Putln("%s = %s(xgb.Get32(buf[b:]))", name, t.SrcName())
    24  		case 8:
    25  			c.Putln("%s = %s(xgb.Get64(buf[b:]))", name, t.SrcName())
    26  		}
    27  	case *Base:
    28  		// If this is a bool, stop short and do something special.
    29  		if t.SrcName() == "bool" {
    30  			c.Putln("if buf[b] == 1 {")
    31  			c.Putln("%s = true", name)
    32  			c.Putln("} else {")
    33  			c.Putln("%s = false", name)
    34  			c.Putln("}")
    35  			break
    36  		}
    37  
    38  		var val string
    39  		switch t.Size().Eval() {
    40  		case 1:
    41  			val = fmt.Sprintf("buf[b]")
    42  		case 2:
    43  			val = fmt.Sprintf("xgb.Get16(buf[b:])")
    44  		case 4:
    45  			val = fmt.Sprintf("xgb.Get32(buf[b:])")
    46  		case 8:
    47  			val = fmt.Sprintf("xgb.Get64(buf[b:])")
    48  		}
    49  
    50  		// We need to convert base types if they aren't uintXX or byte
    51  		ty := t.SrcName()
    52  		if ty != "byte" && ty != "uint16" && ty != "uint32" && ty != "uint64" {
    53  			val = fmt.Sprintf("%s(%s)", ty, val)
    54  		}
    55  		c.Putln("%s = %s", name, val)
    56  	default:
    57  		log.Panicf("Cannot read field '%s' as a simple field with %T type.",
    58  			name, typ)
    59  	}
    60  
    61  	c.Putln("b += %s", typ.Size())
    62  }
    63  
    64  func (f *SingleField) Read(c *Context, prefix string) {
    65  	switch t := f.Type.(type) {
    66  	case *Resource:
    67  		ReadSimpleSingleField(c, fmt.Sprintf("%s%s", prefix, f.SrcName()), t)
    68  	case *TypeDef:
    69  		ReadSimpleSingleField(c, fmt.Sprintf("%s%s", prefix, f.SrcName()), t)
    70  	case *Base:
    71  		ReadSimpleSingleField(c, fmt.Sprintf("%s%s", prefix, f.SrcName()), t)
    72  	case *Struct:
    73  		c.Putln("%s%s = %s{}", prefix, f.SrcName(), t.SrcName())
    74  		c.Putln("b += %sRead(buf[b:], &%s%s)", t.SrcName(), prefix, f.SrcName())
    75  	case *Union:
    76  		c.Putln("%s%s = %s{}", prefix, f.SrcName(), t.SrcName())
    77  		c.Putln("b += %sRead(buf[b:], &%s%s)", t.SrcName(), prefix, f.SrcName())
    78  	default:
    79  		log.Panicf("Cannot read field '%s' with %T type.", f.XmlName(), f.Type)
    80  	}
    81  }
    82  
    83  func WriteSimpleSingleField(c *Context, name string, typ Type) {
    84  	switch t := typ.(type) {
    85  	case *Resource:
    86  		c.Putln("xgb.Put32(buf[b:], uint32(%s))", name)
    87  	case *TypeDef:
    88  		switch t.Size().Eval() {
    89  		case 1:
    90  			c.Putln("buf[b] = byte(%s)", name)
    91  		case 2:
    92  			c.Putln("xgb.Put16(buf[b:], uint16(%s))", name)
    93  		case 4:
    94  			c.Putln("xgb.Put32(buf[b:], uint32(%s))", name)
    95  		case 8:
    96  			c.Putln("xgb.Put64(buf[b:], uint64(%s))", name)
    97  		}
    98  	case *Base:
    99  		// If this is a bool, stop short and do something special.
   100  		if t.SrcName() == "bool" {
   101  			c.Putln("if %s {", name)
   102  			c.Putln("buf[b] = 1")
   103  			c.Putln("} else {")
   104  			c.Putln("buf[b] = 0")
   105  			c.Putln("}")
   106  			break
   107  		}
   108  
   109  		switch t.Size().Eval() {
   110  		case 1:
   111  			if t.SrcName() != "byte" {
   112  				c.Putln("buf[b] = byte(%s)", name)
   113  			} else {
   114  				c.Putln("buf[b] = %s", name)
   115  			}
   116  		case 2:
   117  			if t.SrcName() != "uint16" {
   118  				c.Putln("xgb.Put16(buf[b:], uint16(%s))", name)
   119  			} else {
   120  				c.Putln("xgb.Put16(buf[b:], %s)", name)
   121  			}
   122  		case 4:
   123  			if t.SrcName() != "uint32" {
   124  				c.Putln("xgb.Put32(buf[b:], uint32(%s))", name)
   125  			} else {
   126  				c.Putln("xgb.Put32(buf[b:], %s)", name)
   127  			}
   128  		case 8:
   129  			if t.SrcName() != "uint64" {
   130  				c.Putln("xgb.Put64(buf[b:], uint64(%s))", name)
   131  			} else {
   132  				c.Putln("xgb.Put64(buf[b:], %s)", name)
   133  			}
   134  		}
   135  	default:
   136  		log.Fatalf("Cannot read field '%s' as a simple field with %T type.",
   137  			name, typ)
   138  	}
   139  
   140  	c.Putln("b += %s", typ.Size())
   141  }
   142  
   143  func (f *SingleField) Write(c *Context, prefix string) {
   144  	switch t := f.Type.(type) {
   145  	case *Resource:
   146  		WriteSimpleSingleField(c, fmt.Sprintf("%s%s", prefix, f.SrcName()), t)
   147  	case *TypeDef:
   148  		WriteSimpleSingleField(c, fmt.Sprintf("%s%s", prefix, f.SrcName()), t)
   149  	case *Base:
   150  		WriteSimpleSingleField(c, fmt.Sprintf("%s%s", prefix, f.SrcName()), t)
   151  	case *Union:
   152  		c.Putln("{")
   153  		c.Putln("unionBytes := %s%s.Bytes()", prefix, f.SrcName())
   154  		c.Putln("copy(buf[b:], unionBytes)")
   155  		c.Putln("b += len(unionBytes)")
   156  		c.Putln("}")
   157  	case *Struct:
   158  		c.Putln("{")
   159  		c.Putln("structBytes := %s%s.Bytes()", prefix, f.SrcName())
   160  		c.Putln("copy(buf[b:], structBytes)")
   161  		c.Putln("b += len(structBytes)")
   162  		c.Putln("}")
   163  	default:
   164  		log.Fatalf("Cannot read field '%s' with %T type.", f.XmlName(), f.Type)
   165  	}
   166  }