diff --git a/backends/golang/init.go b/backends/golang/init.go index 0e0cf01..0d8dc6b 100644 --- a/backends/golang/init.go +++ b/backends/golang/init.go @@ -2,19 +2,25 @@ package golang import ( "flag" + "fmt" "go/format" "github.com/andyleap/gencode/schema" ) type GolangBackend struct { - Package string - Unsafe bool + Package string + Unsafe bool + BigEndian bool } func (gb *GolangBackend) Generate(s *schema.Schema) (string, error) { w := &Walker{} w.Unsafe = gb.Unsafe + w.BigEndian = gb.BigEndian + if w.Unsafe && w.BigEndian { + return "", fmt.Errorf("Unsafe and BigEndian incompatible") + } def, err := w.WalkSchema(s, gb.Package) if err != nil { return "", err @@ -30,6 +36,7 @@ func (gb *GolangBackend) Flags() *flag.FlagSet { flags := flag.NewFlagSet("Go", flag.ExitOnError) flags.StringVar(&gb.Package, "package", "main", "package to build the gencode system for") flags.BoolVar(&gb.Unsafe, "unsafe", false, "Generate faster, but unsafe code") + flags.BoolVar(&gb.BigEndian, "bigendian", false, "Generate bigendian code, incompatible with unsafe.") return flags } diff --git a/backends/golang/schema.go b/backends/golang/schema.go index d8a854e..94e1b6f 100644 --- a/backends/golang/schema.go +++ b/backends/golang/schema.go @@ -11,18 +11,19 @@ type Walker struct { Offset int IAdjusted bool Unsafe bool + BigEndian bool } func (w *Walker) WalkSchema(s *schema.Schema, Package string) (parts *StringBuilder, err error) { parts = &StringBuilder{} parts.Append(fmt.Sprintf(`package %s - + import ( "unsafe" "io" "time" ) - + var ( _ = unsafe.Sizeof(0) _ = io.ReadFull diff --git a/backends/golang/type_float.go b/backends/golang/type_float.go index 5a42bcf..355a0e7 100644 --- a/backends/golang/type_float.go +++ b/backends/golang/type_float.go @@ -1,6 +1,7 @@ package golang import ( + "sort" "text/template" "github.com/andyleap/gencode/schema" @@ -12,11 +13,12 @@ var ( func init() { FloatTemps = template.New("FloatTemps").Funcs(template.FuncMap{ - "Bytes": func(bits int) int { - return bits / 8 - }, - "BitRange": func(bits int) []int { - return []int{0, 8, 16, 24, 32, 40, 48, 56, 64}[0:(bits / 8)] + "BitRange": func(bits int, bigEndian bool) []int { + ar := []int{0, 8, 16, 24, 32, 40, 48, 56, 64}[0:(bits / 8)] + if bigEndian { + sort.Sort(sort.Reverse(sort.IntSlice(ar))) + } + return ar }, }) @@ -26,8 +28,8 @@ func init() { *(*float{{.Bits}})(unsafe.Pointer(&buf[{{if .W.IAdjusted}}i + {{end}}{{.W.Offset}}])) = {{.Target}} {{else}} v := *(*uint{{.Bits}})(unsafe.Pointer(&({{.Target}}))) - {{range BitRange .Bits}} - buf[{{if $.W.IAdjusted}}i + {{end}}{{Bytes .}} + {{$.W.Offset}}] = byte(v >> {{.}}) + {{range $pos, $bits := BitRange .Bits .W.BigEndian}} + buf[{{if $.W.IAdjusted}}i + {{end}}{{$pos}} + {{$.W.Offset}}] = byte(v >> {{$bits}}) {{end}} {{end}} }`)) @@ -36,7 +38,7 @@ func init() { {{if .W.Unsafe}} {{.Target}} = *(*float{{.Bits}})(unsafe.Pointer(&buf[{{if .W.IAdjusted}}i + {{end}}{{.W.Offset}}])) {{else}} - v := 0{{range BitRange .Bits}} | (uint{{$.Bits}}(buf[{{if $.W.IAdjusted}}i + {{end}}{{Bytes .}} + {{$.W.Offset}}]) << {{.}}){{end}} + v := 0{{range $pos, $bits := BitRange .Bits .W.BigEndian}} | (uint{{$.Bits}}(buf[{{if $.W.IAdjusted}}i + {{end}}{{$pos}} + {{$.W.Offset}}]) << {{$bits}}){{end}} {{.Target}} = *(*float{{.Bits}})(unsafe.Pointer(&v)) {{end}} }`)) diff --git a/backends/golang/type_int.go b/backends/golang/type_int.go index a1fd3ff..7cd9d1f 100644 --- a/backends/golang/type_int.go +++ b/backends/golang/type_int.go @@ -1,6 +1,7 @@ package golang import ( + "sort" "text/template" "github.com/andyleap/gencode/schema" @@ -12,18 +13,19 @@ var ( func init() { IntTemps = template.New("IntTemps").Funcs(template.FuncMap{ - "Bytes": func(bits int) int { - return bits / 8 - }, - "BitRange": func(bits int) []int { - return []int{0, 8, 16, 24, 32, 40, 48, 56, 64}[0:(bits / 8)] + "BitRange": func(bits int, bigEndian bool) []int { + ar := []int{0, 8, 16, 24, 32, 40, 48, 56, 64}[0:(bits / 8)] + if bigEndian { + sort.Sort(sort.Reverse(sort.IntSlice(ar))) + } + return ar }, }) template.Must(IntTemps.New("marshal").Parse(` { {{if .VarInt }} - + t := uint{{.Bits}}({{.Target}}) {{if .Signed}} t <<= 1 @@ -38,17 +40,17 @@ func init() { } buf[i + {{.W.Offset}}] = byte(t) i++ - + {{else}} - + {{if .W.Unsafe}} *(*{{if not .Signed}}u{{end}}int{{.Bits}})(unsafe.Pointer(&buf[{{if $.W.IAdjusted}}i + {{end}}{{$.W.Offset}}])) = {{.Target}} {{else}} - {{range BitRange .Bits}} - buf[{{if $.W.IAdjusted}}i + {{end}}{{Bytes .}} + {{$.W.Offset}}] = byte({{$.Target}} >> {{.}}) + {{range $pos, $bits := BitRange .Bits .W.BigEndian}} + buf[{{if $.W.IAdjusted}}i + {{end}}{{$pos}} + {{$.W.Offset}}] = byte({{$.Target}} >> {{$bits}}) {{end}} {{end}} - + {{end}} }`)) template.Must(IntTemps.New("unmarshal").Parse(` @@ -70,15 +72,15 @@ func init() { {{else}} {{.Target}} = t {{end}} - + {{else}} - + {{if .W.Unsafe}} {{.Target}} = *(*{{if not .Signed}}u{{end}}int{{.Bits}})(unsafe.Pointer(&buf[{{if $.W.IAdjusted}}i + {{end}}{{$.W.Offset}}])) {{else}} - {{$.Target}} = 0{{range BitRange .Bits}} | ({{if not $.Signed}}u{{end}}int{{$.Bits}}(buf[{{if $.W.IAdjusted}}i + {{end}}{{Bytes .}} + {{$.W.Offset}}]) << {{.}}){{end}} + {{$.Target}} = 0{{range $pos, $bits := BitRange .Bits .W.BigEndian}} | ({{if not $.Signed}}u{{end}}int{{$.Bits}}(buf[{{if $.W.IAdjusted}}i + {{end}}{{$pos}} + {{$.W.Offset}}]) << {{$bits}}){{end}} {{end}} - + {{end}} }`)) template.Must(IntTemps.New("field").Parse(`{{if not .Signed}}u{{end}}int{{.Bits}}`))