diff options
Diffstat (limited to 'nexgb')
| -rw-r--r-- | nexgb/xgbgen/expression.go | 28 | ||||
| -rw-r--r-- | nexgb/xgbgen/field.go | 31 | ||||
| -rw-r--r-- | nexgb/xgbgen/go.go | 301 | ||||
| -rw-r--r-- | nexgb/xgbgen/go_error.go | 39 | ||||
| -rw-r--r-- | nexgb/xgbgen/go_event.go | 38 | ||||
| -rw-r--r-- | nexgb/xgbgen/go_list.go | 75 | ||||
| -rw-r--r-- | nexgb/xgbgen/go_single_field.go | 138 | ||||
| -rw-r--r-- | nexgb/xgbgen/go_struct.go | 107 | ||||
| -rw-r--r-- | nexgb/xgbgen/go_union.go | 15 | 
9 files changed, 503 insertions, 269 deletions
| diff --git a/nexgb/xgbgen/expression.go b/nexgb/xgbgen/expression.go index 7099c25..a975320 100644 --- a/nexgb/xgbgen/expression.go +++ b/nexgb/xgbgen/expression.go @@ -13,6 +13,34 @@ type Expression interface {  	Initialize(p *Protocol)  } +// Function is a custom expression not found in the XML. It's simply used +// to apply a function named in 'Name' to the Expr expression. +type Function struct { +	Name string +	Expr Expression +} + +func (e *Function) Concrete() bool { +	return false +} + +func (e *Function) Eval() uint { +	log.Fatalf("Cannot evaluate a 'Function'. It is not concrete.") +	panic("unreachable") +} + +func (e *Function) Reduce(prefix, fun string) string { +	return fmt.Sprintf("%s(%s)", e.Name, e.Expr.Reduce(prefix, fun)) +} + +func (e *Function) String() string { +	return e.Reduce("", "") +} + +func (e *Function) Initialize(p *Protocol) { +	e.Expr.Initialize(p) +} +  type BinaryOp struct {  	Op    string  	Expr1 Expression diff --git a/nexgb/xgbgen/field.go b/nexgb/xgbgen/field.go index ed113e0..0f2323e 100644 --- a/nexgb/xgbgen/field.go +++ b/nexgb/xgbgen/field.go @@ -1,5 +1,10 @@  package main +import ( +	"fmt" +	"log" +) +  type Field interface {  	Initialize(p *Protocol)  	SrcName() string @@ -8,6 +13,7 @@ type Field interface {  	Define(c *Context)  	Read(c *Context) +	Write(c *Context)  }  func (pad *PadField) Initialize(p *Protocol) {} @@ -66,8 +72,31 @@ func (f *ListField) XmlName() string {  	return f.xmlName  } +// func (f *ListField) Size() Size {  +	// return newExpressionSize(f.LengthExpr).Multiply(f.Type.Size())  +// }  +  func (f *ListField) Size() Size { -	return newExpressionSize(f.LengthExpr).Multiply(f.Type.Size()) +	simpleLen := &Function{ +		Name: "pad", +		Expr: newBinaryOp("*", f.LengthExpr, f.Type.Size().Expression), +	} + +	switch f.Type.(type) { +	case *Struct: +		sizeFun := &Function{ +			Name: fmt.Sprintf("%sListSize", f.Type.SrcName()), +			Expr: &FieldRef{Name: f.SrcName()}, +		} +		return newExpressionSize(sizeFun) +	case *Base: +		return newExpressionSize(simpleLen) +	case *Resource: +		return newExpressionSize(simpleLen) +	default: +		log.Fatalf("Cannot compute list size with type '%T'.", f.Type) +	} +	panic("unreachable")  }  func (f *ListField) Initialize(p *Protocol) { diff --git a/nexgb/xgbgen/go.go b/nexgb/xgbgen/go.go index 014b76b..11e413b 100644 --- a/nexgb/xgbgen/go.go +++ b/nexgb/xgbgen/go.go @@ -1,10 +1,5 @@  package main -import ( -	"fmt" -	"log" -) -  // xgbResourceIdName is the name of the type used for all resource identifiers.  // As of right now, it needs to be declared somewhere manually.  var xgbGenResourceIdName = "Id" @@ -92,173 +87,6 @@ func (td *TypeDef) Define(c *Context) {  	c.Putln("")  } -// Struct types -func (s *Struct) Define(c *Context) { -	c.Putln("// '%s' struct definition", s.SrcName()) -	c.Putln("// Size: %s", s.Size()) -	c.Putln("type %s struct {", s.SrcName()) -	for _, field := range s.Fields { -		field.Define(c) -	} -	c.Putln("}") -	c.Putln("") - -	// Write function that reads bytes and produces this struct. -	s.Read(c) - -	// Write function that reads a list of this structs. -	s.ReadList(c) - -	// Write function that writes bytes given this struct. -	s.Write(c) - -	// Write function that writes a list of this struct. -	s.WriteList(c) -} - -// Read for a struct creates a function 'NewStructName' that takes a byte -// slice and produces TWO values: an instance of 'StructName' and the number -// of bytes read from the byte slice. -// 'NewStructName' should only be used to read raw reply data from the wire. -func (s *Struct) Read(c *Context) { -	c.Putln("// Struct read %s", s.SrcName()) -	c.Putln("func New%s(buf []byte) (%s, int) {", s.SrcName(), s.SrcName()) - -	c.Putln("v := %s{}", s.SrcName()) -	c.Putln("b := 0") -	c.Putln("consumed := 0") -	c.Putln("consumed = 0 + consumed // no-op") // dirty hack for a no-op -	c.Putln("") -	for _, field := range s.Fields { -		field.Read(c) -	} -	c.Putln("return v, b") - -	c.Putln("}") -	c.Putln("") -} - -// ReadList for a struct creates a function 'ReadStructNameList' that takes -// a byte slice and a length and produces TWO values: an slice of StructName  -// and the number of bytes read from the byte slice. -func (s *Struct) ReadList(c *Context) { -	c.Putln("// Struct list read %s", s.SrcName()) -	c.Putln("func Read%sList(buf []byte, length int) ([]%s, int) {", -		s.SrcName(), s.SrcName()) - -	c.Putln("v := make([]%s, length)", s.SrcName()) -	c.Putln("b := 0") -	c.Putln("consumed := 0") -	c.Putln("consumed = 0 + consumed // no-op") // dirty hack for a no-op -	c.Putln("for i := 0; i < length; i++ {") -	c.Putln("v[i], consumed = New%s(buf[b:])", s.SrcName()) -	c.Putln("b += consumed") -	c.Putln("}") - -	c.Putln("return v, pad(b)") - -	c.Putln("}") -	c.Putln("") -} - -func (s *Struct) Write(c *Context) { -	c.Putln("// Struct write %s", s.SrcName()) -	c.Putln("") -} - -func (s *Struct) WriteList(c *Context) { -	c.Putln("// Write struct list %s", s.SrcName()) -	c.Putln("") -} - -// Union types -func (u *Union) Define(c *Context) { -	c.Putln("// Union definition %s", u.SrcName()) -} - -func (u *Union) Read(c *Context, prefix string) { -	c.Putln("// Union read %s", u.SrcName()) -} - -func (u *Union) Write(c *Context, prefix string) { -	c.Putln("// Union write %s", u.SrcName()) -} - -// Event types -func (e *Event) Define(c *Context) { -	c.Putln("// Event definition %s (%d)", e.SrcName(), e.Number) -} - -func (e *Event) Read(c *Context, prefix string) { -	c.Putln("// Event read %s", e.SrcName()) -} - -func (e *Event) Write(c *Context, prefix string) { -	c.Putln("// Event write %s", e.SrcName()) -} - -// EventCopy types -func (e *EventCopy) Define(c *Context) { -	c.Putln("// EventCopy definition %s (%d)", e.SrcName(), e.Number) -	c.Putln("") -	c.Putln("const %s = %d", e.SrcName(), e.Number) -	c.Putln("") -	c.Putln("type %s %s", e.EvType(), e.Old.(*Event).EvType()) -	c.Putln("") -	c.Putln("func New%s(buf []byte) %s {", e.SrcName(), e.EvType()) -	c.Putln("return (%s)(New%s(buf))", e.EvType(), e.Old.SrcName()) -	c.Putln("}") -	c.Putln("") -	c.Putln("func (ev %s) ImplementsEvent() { }", e.EvType()) -	c.Putln("") -	c.Putln("func (ev %s) Bytes() []byte {", e.EvType()) -	c.Putln("return (%s)(ev).Bytes()", e.Old.(*Event).EvType()) -	c.Putln("}") -	c.Putln("") -	c.Putln("func init() {") -	c.Putln("newEventFuncs[%d] = New%s", e.Number, e.SrcName()) -	c.Putln("}") -	c.Putln("") -} - -// Error types -func (e *Error) Define(c *Context) { -	c.Putln("// Error definition %s (%d)", e.SrcName(), e.Number) -	c.Putln("") -} - -func (e *Error) Read(c *Context, prefix string) { -	c.Putln("// Error read %s", e.SrcName()) -} - -func (e *Error) Write(c *Context, prefix string) { -	c.Putln("// Error write %s", e.SrcName()) -} - -// ErrorCopy types -func (e *ErrorCopy) Define(c *Context) { -	c.Putln("// ErrorCopy definition %s (%d)", e.SrcName(), e.Number) -	c.Putln("") -	c.Putln("const %s = %d", e.ErrConst(), e.Number) -	c.Putln("") -	c.Putln("type %s %s", e.ErrType(), e.Old.(*Error).ErrType()) -	c.Putln("") -	c.Putln("func New%s(buf []byte) %s {", e.SrcName(), e.ErrType()) -	c.Putln("return (%s)(New%s(buf))", e.ErrType(), e.Old.SrcName()) -	c.Putln("}") -	c.Putln("") -	c.Putln("func (err %s) ImplementsError() { }", e.ErrType()) -	c.Putln("") -	c.Putln("func (err %s) Bytes() []byte {", e.ErrType()) -	c.Putln("return (%s)(err).Bytes()", e.Old.(*Error).ErrType()) -	c.Putln("}") -	c.Putln("") -	c.Putln("func init() {") -	c.Putln("newErrorFuncs[%d] = New%s", e.Number, e.SrcName()) -	c.Putln("}") -	c.Putln("") -} -  // Field definitions, reads and writes.  // Pad fields @@ -268,143 +96,80 @@ func (f *PadField) Define(c *Context) {  func (f *PadField) Read(c *Context) {  	c.Putln("b += %s // padding", f.Size()) -	c.Putln("")  } -// Single fields -func (f *SingleField) Define(c *Context) { -	c.Putln("%s %s", f.SrcName(), f.Type.SrcName()) -} - -func ReadSimpleSingleField(c *Context, name string, typ Type) { -	switch t := typ.(type) { -	case *Resource: -		c.Putln("%s = get32(buf[b:])", name) -	case *TypeDef: -		switch t.Size().Eval() { -		case 1: -			c.Putln("%s = %s(buf[b])", name, t.SrcName()) -		case 2: -			c.Putln("%s = %s(get16(buf[b:]))", name, t.SrcName()) -		case 4: -			c.Putln("%s = %s(get32(buf[b:]))", name, t.SrcName()) -		case 8: -			c.Putln("%s = %s(get64(buf[b:]))", name, t.SrcName()) -		} -	case *Base: -		var val string -		switch t.Size().Eval() { -		case 1: -			val = fmt.Sprintf("buf[b]") -		case 2: -			val = fmt.Sprintf("get16(buf[b:])") -		case 4: -			val = fmt.Sprintf("get32(buf[b:])") -		case 8: -			val = fmt.Sprintf("get64(buf[b:])") -		} - -		// We need to convert base types if they aren't uintXX or byte -		ty := t.SrcName() -		if ty != "byte" && ty != "uint16" && ty != "uint32" && ty != "uint64" { -			val = fmt.Sprintf("%s(%s)", ty, val) -		} -		c.Putln("%s = %s", name, val) -	default: -		log.Fatalf("Cannot read field '%s' as a simple field with %T type.", -			name, typ) -	} - -	c.Putln("b += %s", typ.Size()) -} - -func (f *SingleField) Read(c *Context) { -	switch t := f.Type.(type) { -	case *Resource: -		ReadSimpleSingleField(c, fmt.Sprintf("v.%s", f.SrcName()), t) -	case *TypeDef: -		ReadSimpleSingleField(c, fmt.Sprintf("v.%s", f.SrcName()), t) -	case *Base: -		ReadSimpleSingleField(c, fmt.Sprintf("v.%s", f.SrcName()), t) -	case *Struct: -		c.Putln("v.%s, consumed = New%s(buf[b:])", f.SrcName(), t.SrcName()) -		c.Putln("b += consumed") -		c.Putln("") -	default: -		log.Fatalf("Cannot read field '%s' with %T type.", f.XmlName(), f.Type) -	} -} - -// List fields -func (f *ListField) Define(c *Context) { -	c.Putln("%s []%s // length: %s", -		f.SrcName(), f.Type.SrcName(), f.Size()) -} - -func (f *ListField) Read(c *Context) { -	switch t := f.Type.(type) { -	case *Resource: -		length := f.LengthExpr.Reduce("v.", "") -		c.Putln("v.%s = make([]Id, %s)", f.SrcName(), length) -		c.Putln("for i := 0; i < %s; i++ {", length) -		ReadSimpleSingleField(c, fmt.Sprintf("v.%s[i]", f.SrcName()), t) -		c.Putln("}") -		c.Putln("") -	case *Base: -		length := f.LengthExpr.Reduce("v.", "") -		c.Putln("v.%s = make([]%s, %s)", f.SrcName(), t.SrcName(), length) -		c.Putln("for i := 0; i < %s; i++ {", length) -		ReadSimpleSingleField(c, fmt.Sprintf("v.%s[i]", f.SrcName()), t) -		c.Putln("}") -		c.Putln("") -	case *Struct: -		c.Putln("v.%s, consumed = Read%sList(buf[b:], %s)", -			f.SrcName(), t.SrcName(), f.LengthExpr.Reduce("v.", "")) -		c.Putln("b += consumed") -		c.Putln("") -	default: -		log.Fatalf("Cannot read list field '%s' with %T type.", -			f.XmlName(), f.Type) -	} +func (f *PadField) Write(c *Context) { +	c.Putln("b += %s // padding", f.Size())  }  // Local fields  func (f *LocalField) Define(c *Context) {  	c.Putln("// local field: %s %s", f.SrcName(), f.Type.SrcName()) +	panic("todo")  }  func (f *LocalField) Read(c *Context) {  	c.Putln("// reading local field: %s (%s) :: %s",  		f.SrcName(), f.Size(), f.Type.SrcName()) +	panic("todo") +} + +func (f *LocalField) Write(c *Context) { +	c.Putln("// writing local field: %s (%s) :: %s", +		f.SrcName(), f.Size(), f.Type.SrcName()) +	panic("todo")  }  // Expr fields  func (f *ExprField) Define(c *Context) {  	c.Putln("// expression field: %s %s (%s)",  		f.SrcName(), f.Type.SrcName(), f.Expr) +	panic("todo")  }  func (f *ExprField) Read(c *Context) {  	c.Putln("// reading expression field: %s (%s) (%s) :: %s",  		f.SrcName(), f.Size(), f.Expr, f.Type.SrcName()) +	panic("todo") +} + +func (f *ExprField) Write(c *Context) { +	c.Putln("// writing expression field: %s (%s) (%s) :: %s", +		f.SrcName(), f.Size(), f.Expr, f.Type.SrcName()) +	panic("todo")  }  // Value field  func (f *ValueField) Define(c *Context) {  	c.Putln("// valueparam field: type: %s, mask name: %s, list name: %s",  		f.MaskType.SrcName(), f.MaskName, f.ListName) +	panic("todo")  }  func (f *ValueField) Read(c *Context) {  	c.Putln("// reading valueparam: type: %s, mask name: %s, list name: %s",  		f.MaskType.SrcName(), f.MaskName, f.ListName) +	panic("todo") +} + +func (f *ValueField) Write(c *Context) { +	c.Putln("// writing valueparam: type: %s, mask name: %s, list name: %s", +		f.MaskType.SrcName(), f.MaskName, f.ListName) +	panic("todo")  }  // Switch field  func (f *SwitchField) Define(c *Context) {  	c.Putln("// switch field: %s (%s)", f.Name, f.Expr) +	panic("todo")  }  func (f *SwitchField) Read(c *Context) {  	c.Putln("// reading switch field: %s (%s)", f.Name, f.Expr) +	panic("todo") +} + +func (f *SwitchField) Write(c *Context) { +	c.Putln("// writing switch field: %s (%s)", f.Name, f.Expr) +	panic("todo")  } diff --git a/nexgb/xgbgen/go_error.go b/nexgb/xgbgen/go_error.go new file mode 100644 index 0000000..0cb77cc --- /dev/null +++ b/nexgb/xgbgen/go_error.go @@ -0,0 +1,39 @@ +package main + +// Error types +func (e *Error) Define(c *Context) { +	c.Putln("// Error definition %s (%d)", e.SrcName(), e.Number) +	c.Putln("") +} + +func (e *Error) Read(c *Context, prefix string) { +	c.Putln("// Error read %s", e.SrcName()) +} + +func (e *Error) Write(c *Context, prefix string) { +	c.Putln("// Error write %s", e.SrcName()) +} + +// ErrorCopy types +func (e *ErrorCopy) Define(c *Context) { +	c.Putln("// ErrorCopy definition %s (%d)", e.SrcName(), e.Number) +	c.Putln("") +	c.Putln("const %s = %d", e.ErrConst(), e.Number) +	c.Putln("") +	c.Putln("type %s %s", e.ErrType(), e.Old.(*Error).ErrType()) +	c.Putln("") +	c.Putln("func New%s(buf []byte) %s {", e.SrcName(), e.ErrType()) +	c.Putln("return (%s)(New%s(buf))", e.ErrType(), e.Old.SrcName()) +	c.Putln("}") +	c.Putln("") +	c.Putln("func (err %s) ImplementsError() { }", e.ErrType()) +	c.Putln("") +	c.Putln("func (err %s) Bytes() []byte {", e.ErrType()) +	c.Putln("return (%s)(err).Bytes()", e.Old.(*Error).ErrType()) +	c.Putln("}") +	c.Putln("") +	c.Putln("func init() {") +	c.Putln("newErrorFuncs[%d] = New%s", e.Number, e.SrcName()) +	c.Putln("}") +	c.Putln("") +} diff --git a/nexgb/xgbgen/go_event.go b/nexgb/xgbgen/go_event.go new file mode 100644 index 0000000..d91fd7a --- /dev/null +++ b/nexgb/xgbgen/go_event.go @@ -0,0 +1,38 @@ +package main + +// Event types +func (e *Event) Define(c *Context) { +	c.Putln("// Event definition %s (%d)", e.SrcName(), e.Number) +} + +func (e *Event) Read(c *Context, prefix string) { +	c.Putln("// Event read %s", e.SrcName()) +} + +func (e *Event) Write(c *Context, prefix string) { +	c.Putln("// Event write %s", e.SrcName()) +} + +// EventCopy types +func (e *EventCopy) Define(c *Context) { +	c.Putln("// EventCopy definition %s (%d)", e.SrcName(), e.Number) +	c.Putln("") +	c.Putln("const %s = %d", e.SrcName(), e.Number) +	c.Putln("") +	c.Putln("type %s %s", e.EvType(), e.Old.(*Event).EvType()) +	c.Putln("") +	c.Putln("func New%s(buf []byte) %s {", e.SrcName(), e.EvType()) +	c.Putln("return (%s)(New%s(buf))", e.EvType(), e.Old.SrcName()) +	c.Putln("}") +	c.Putln("") +	c.Putln("func (ev %s) ImplementsEvent() { }", e.EvType()) +	c.Putln("") +	c.Putln("func (ev %s) Bytes() []byte {", e.EvType()) +	c.Putln("return (%s)(ev).Bytes()", e.Old.(*Event).EvType()) +	c.Putln("}") +	c.Putln("") +	c.Putln("func init() {") +	c.Putln("newEventFuncs[%d] = New%s", e.Number, e.SrcName()) +	c.Putln("}") +	c.Putln("") +} diff --git a/nexgb/xgbgen/go_list.go b/nexgb/xgbgen/go_list.go new file mode 100644 index 0000000..03da22e --- /dev/null +++ b/nexgb/xgbgen/go_list.go @@ -0,0 +1,75 @@ +package main + +import ( +	"fmt" +	"log" +) + +// List fields +func (f *ListField) Define(c *Context) { +	c.Putln("%s []%s // size: %s", +		f.SrcName(), f.Type.SrcName(), f.Size()) +} + +func (f *ListField) Read(c *Context) { +	c.Putln("") + +	switch t := f.Type.(type) { +	case *Resource: +		length := f.LengthExpr.Reduce("v.", "") +		c.Putln("v.%s = make([]Id, %s)", f.SrcName(), length) +		c.Putln("for i := 0; i < %s; i++ {", length) +		ReadSimpleSingleField(c, fmt.Sprintf("v.%s[i]", f.SrcName()), t) +		c.Putln("}") +		c.Putln("b = pad(b)") +	case *Base: +		length := f.LengthExpr.Reduce("v.", "") +		c.Putln("v.%s = make([]%s, %s)", f.SrcName(), t.SrcName(), length) +		if t.SrcName() == "byte" { +			c.Putln("copy(v.%s[:%s], buf[b:])", f.SrcName(), length) +			c.Putln("b += pad(%s)", length) +		} else { +			c.Putln("for i := 0; i < %s; i++ {", length) +			ReadSimpleSingleField(c, fmt.Sprintf("v.%s[i]", f.SrcName()), t) +			c.Putln("}") +			c.Putln("b = pad(b)") +		} +	case *Struct: +		c.Putln("v.%s = make([]%s, %s)", +			f.SrcName(), t.SrcName(), f.LengthExpr.Reduce("v.", "")) +		c.Putln("b += Read%sList(buf[b:], v.%s)", t.SrcName(), f.SrcName()) +	default: +		log.Fatalf("Cannot read list field '%s' with %T type.", +			f.XmlName(), f.Type) +	} +} + +func (f *ListField) Write(c *Context) { +	c.Putln("") + +	switch t := f.Type.(type) { +	case *Resource: +		length := f.LengthExpr.Reduce("v.", "") +		c.Putln("for i := 0; i < %s; i++", length) +		WriteSimpleSingleField(c, fmt.Sprintf("v.%s[i]", f.SrcName()), t) +		c.Putln("}") +		c.Putln("b = pad(b)") +	case *Base: +		length := f.LengthExpr.Reduce("v.", "") +		if t.SrcName() == "byte" { +			c.Putln("copy(buf[b:], v.%s[:%s])", f.SrcName(), length) +			c.Putln("b += pad(%s)", length) +		} else { +			c.Putln("for i := 0; i < %s; i++ {", length) +			WriteSimpleSingleField(c, fmt.Sprintf("v.%s[i]", f.SrcName()), t) +			c.Putln("}") +			c.Putln("b = pad(b)") +		} +	case *Struct: +		c.Putln("b += %sListBytes(buf[b:], v.%s)", t.SrcName(), f.SrcName()) +	default: +		log.Fatalf("Cannot read list field '%s' with %T type.", +			f.XmlName(), f.Type) +	} +} + diff --git a/nexgb/xgbgen/go_single_field.go b/nexgb/xgbgen/go_single_field.go new file mode 100644 index 0000000..3c354e7 --- /dev/null +++ b/nexgb/xgbgen/go_single_field.go @@ -0,0 +1,138 @@ +package main + +import ( +	"fmt" +	"log" +) + +func (f *SingleField) Define(c *Context) { +	c.Putln("%s %s", f.SrcName(), f.Type.SrcName()) +} + +func ReadSimpleSingleField(c *Context, name string, typ Type) { +	switch t := typ.(type) { +	case *Resource: +		c.Putln("%s = get32(buf[b:])", name) +	case *TypeDef: +		switch t.Size().Eval() { +		case 1: +			c.Putln("%s = %s(buf[b])", name, t.SrcName()) +		case 2: +			c.Putln("%s = %s(get16(buf[b:]))", name, t.SrcName()) +		case 4: +			c.Putln("%s = %s(get32(buf[b:]))", name, t.SrcName()) +		case 8: +			c.Putln("%s = %s(get64(buf[b:]))", name, t.SrcName()) +		} +	case *Base: +		var val string +		switch t.Size().Eval() { +		case 1: +			val = fmt.Sprintf("buf[b]") +		case 2: +			val = fmt.Sprintf("get16(buf[b:])") +		case 4: +			val = fmt.Sprintf("get32(buf[b:])") +		case 8: +			val = fmt.Sprintf("get64(buf[b:])") +		} + +		// We need to convert base types if they aren't uintXX or byte +		ty := t.SrcName() +		if ty != "byte" && ty != "uint16" && ty != "uint32" && ty != "uint64" { +			val = fmt.Sprintf("%s(%s)", ty, val) +		} +		c.Putln("%s = %s", name, val) +	default: +		log.Fatalf("Cannot read field '%s' as a simple field with %T type.", +			name, typ) +	} + +	c.Putln("b += %s", typ.Size()) +} + +func (f *SingleField) Read(c *Context) { +	switch t := f.Type.(type) { +	case *Resource: +		ReadSimpleSingleField(c, fmt.Sprintf("v.%s", f.SrcName()), t) +	case *TypeDef: +		ReadSimpleSingleField(c, fmt.Sprintf("v.%s", f.SrcName()), t) +	case *Base: +		ReadSimpleSingleField(c, fmt.Sprintf("v.%s", f.SrcName()), t) +	case *Struct: +		c.Putln("v.%s = %s{}", f.SrcName(), t.SrcName()) +		c.Putln("b += Read%s(buf[b:], &v.%s)", t.SrcName(), f.SrcName()) +		c.Putln("") +	default: +		log.Fatalf("Cannot read field '%s' with %T type.", f.XmlName(), f.Type) +	} +} + +func WriteSimpleSingleField(c *Context, name string, typ Type) { +	switch t := typ.(type) { +	case *Resource: +		c.Putln("put32(buf[b:], uint32(%s))", name) +	case *TypeDef: +		switch t.Size().Eval() { +		case 1: +			c.Putln("buf[b] = byte(%s)", name) +		case 2: +			c.Putln("put16(buf[b:], uint16(%s))", name) +		case 4: +			c.Putln("put32(buf[b:], uint32(%s))", name) +		case 8: +			c.Putln("put64(buf[b:], uint64(%s))", name) +		} +	case *Base: +		switch t.Size().Eval() { +		case 1: +			if t.SrcName() != "byte" { +				c.Putln("buf[b] = byte(%s)", name) +			} else { +				c.Putln("buf[b] = %s", name) +			} +		case 2: +			if t.SrcName() != "uint16" { +				c.Putln("put16(buf[b:], uint16(%s))", name) +			} else { +				c.Putln("put16(buf[b:], %s)", name) +			} +		case 4: +			if t.SrcName() != "uint32" { +				c.Putln("put32(buf[b:], uint32(%s))", name) +			} else { +				c.Putln("put32(buf[b:], %s)", name) +			} +		case 8: +			if t.SrcName() != "uint64" { +				c.Putln("put64(buf[b:], uint64(%s))", name) +			} else { +				c.Putln("put64(buf[b:], %s)", name) +			} +		} +	default: +		log.Fatalf("Cannot read field '%s' as a simple field with %T type.", +			name, typ) +	} + +	c.Putln("b += %s", typ.Size()) +} + +func (f *SingleField) Write(c *Context) { +	switch t := f.Type.(type) { +	case *Resource: +		ReadSimpleSingleField(c, fmt.Sprintf("v.%s", f.SrcName()), t) +	case *TypeDef: +		ReadSimpleSingleField(c, fmt.Sprintf("v.%s", f.SrcName()), t) +	case *Base: +		ReadSimpleSingleField(c, fmt.Sprintf("v.%s", f.SrcName()), t) +	case *Struct: +		c.Putln("{") +		c.Putln("structBytes := v.%s.Bytes()", f.SrcName()) +		c.Putln("copy(buf[b:], structBytes)") +		c.Putln("b += len(structBytes)") +		c.Putln("}") +	default: +		log.Fatalf("Cannot read field '%s' with %T type.", f.XmlName(), f.Type) +	} +} diff --git a/nexgb/xgbgen/go_struct.go b/nexgb/xgbgen/go_struct.go new file mode 100644 index 0000000..6925c88 --- /dev/null +++ b/nexgb/xgbgen/go_struct.go @@ -0,0 +1,107 @@ +package main + +func (s *Struct) Define(c *Context) { +	c.Putln("// '%s' struct definition", s.SrcName()) +	c.Putln("// Size: %s", s.Size()) +	c.Putln("type %s struct {", s.SrcName()) +	for _, field := range s.Fields { +		field.Define(c) +	} +	c.Putln("}") +	c.Putln("") + +	// Write function that reads bytes and produces this struct. +	s.Read(c) + +	// Write function that reads a list of this structs. +	s.ReadList(c) + +	// Write function that writes bytes given this struct. +	s.Write(c) + +	// Write function that writes a list of this struct. +	s.WriteList(c) + +	// Write function that computes the size of a list of these structs. +	s.WriteListSize(c) +} + +// Read for a struct creates a function 'ReadStructName' that takes a source  +// byte slice (i.e., the buffer) and a destination struct, and returns +// the number of bytes read off the buffer. +// 'ReadStructName' should only be used to read raw reply data from the wire. +func (s *Struct) Read(c *Context) { +	c.Putln("// Struct read %s", s.SrcName()) +	c.Putln("func Read%s(buf []byte, v *%s) int {", s.SrcName(), s.SrcName()) + +	c.Putln("b := 0") +	c.Putln("") +	for _, field := range s.Fields { +		field.Read(c) +	} +	c.Putln("return b") + +	c.Putln("}") +	c.Putln("") +} + +// ReadList for a struct creates a function 'ReadStructNameList' that takes +// a source (i.e., the buffer) byte slice, and a destination slice and returns  +// the number of bytes read from the byte slice. +func (s *Struct) ReadList(c *Context) { +	c.Putln("// Struct list read %s", s.SrcName()) +	c.Putln("func Read%sList(buf []byte, dest []%s) int {", +		s.SrcName(), s.SrcName()) + +	c.Putln("b := 0") +	c.Putln("for i := 0; i < len(dest); i++ {") +	c.Putln("dest[i] = %s{}", s.SrcName()) +	c.Putln("b += Read%s(buf[b:], &dest[i])", s.SrcName()) +	c.Putln("}") + +	c.Putln("return pad(b)") + +	c.Putln("}") +	c.Putln("") +} + +func (s *Struct) Write(c *Context) { +	c.Putln("// Struct write %s", s.SrcName()) +	c.Putln("func (v %s) Bytes() []byte {", s.SrcName()) +	c.Putln("buf := make([]byte, %s)", s.Size().Reduce("s.", "")) +	c.Putln("b := 0") +	c.Putln("") +	for _, field := range s.Fields { +		field.Write(c) +	} +	c.Putln("return buf") +	c.Putln("}") +	c.Putln("") +} + +func (s *Struct) WriteList(c *Context) { +	c.Putln("// Write struct list %s", s.SrcName()) +	c.Putln("func %sListBytes(buf []byte, list []%s) int {", +		s.SrcName(), s.SrcName()) +	c.Putln("b := 0") +	c.Putln("var structBytes []byte") +	c.Putln("for _, item := range list {") +	c.Putln("structBytes = item.Bytes()") +	c.Putln("copy(buf[b:], len(structBytes))") +	c.Putln("b += len(structBytes)") +	c.Putln("}") +	c.Putln("return b") +	c.Putln("}") +} + +func (s *Struct) WriteListSize(c *Context) { +	c.Putln("// Struct list size %s", s.SrcName()) +	c.Putln("func %sListSize(list []%s) int {", s.SrcName(), s.SrcName()) +	c.Putln("size := 0") +	c.Putln("for _, item := range list {") +	c.Putln("size += %s", s.Size().Reduce("item.", "")) +	c.Putln("}") +	c.Putln("return pad(size)") +	c.Putln("}") +	c.Putln("") +} diff --git a/nexgb/xgbgen/go_union.go b/nexgb/xgbgen/go_union.go new file mode 100644 index 0000000..5721c49 --- /dev/null +++ b/nexgb/xgbgen/go_union.go @@ -0,0 +1,15 @@ +package main + +// Union types +func (u *Union) Define(c *Context) { +	c.Putln("// Union definition %s", u.SrcName()) +} + +func (u *Union) Read(c *Context, prefix string) { +	c.Putln("// Union read %s", u.SrcName()) +} + +func (u *Union) Write(c *Context, prefix string) { +	c.Putln("// Union write %s", u.SrcName()) +} + | 
