PROTON-827: Restore genwrap.go generator deleted in error, update for package 
name changes.


Project: http://git-wip-us.apache.org/repos/asf/qpid-proton/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-proton/commit/5ea911e3
Tree: http://git-wip-us.apache.org/repos/asf/qpid-proton/tree/5ea911e3
Diff: http://git-wip-us.apache.org/repos/asf/qpid-proton/diff/5ea911e3

Branch: refs/heads/go1
Commit: 5ea911e35df9101ca62dbd33e6a232c8e7daa740
Parents: 4f6389a
Author: Alan Conway <[email protected]>
Authored: Thu May 14 21:14:01 2015 -0400
Committer: Alan Conway <[email protected]>
Committed: Fri May 22 15:38:27 2015 -0400

----------------------------------------------------------------------
 go/event/genwrap.go | 427 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 427 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/5ea911e3/go/event/genwrap.go
----------------------------------------------------------------------
diff --git a/go/event/genwrap.go b/go/event/genwrap.go
new file mode 100644
index 0000000..094b196
--- /dev/null
+++ b/go/event/genwrap.go
@@ -0,0 +1,427 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+// Code generator to generate a thin Go wrapper API around the C proton API.
+//
+
+package main
+
+import (
+       "flag"
+       "fmt"
+       "io"
+       "io/ioutil"
+       "os"
+       "os/exec"
+       "path"
+       "regexp"
+       "strings"
+       "text/template"
+)
+
+func mixedCase(s string) string {
+       result := ""
+       for _, w := range strings.Split(s, "_") {
+               if w != "" {
+                       result = result + strings.ToUpper(w[0:1]) + 
strings.ToLower(w[1:])
+               }
+       }
+       return result
+}
+
+func mixedCaseTrim(s, prefix string) string {
+       return mixedCase(strings.TrimPrefix(s, prefix))
+}
+
+var templateFuncs = template.FuncMap{"mixedCase": mixedCase, "mixedCaseTrim": 
mixedCaseTrim}
+
+func doTemplate(out io.Writer, data interface{}, tmpl string) {
+       
panicIf(template.Must(template.New("").Funcs(templateFuncs).Parse(tmpl)).Execute(out,
 data))
+}
+
+type enumType struct {
+       Name   string
+       Values []string
+}
+
+// Find enums in a header file return map of enum name to values.
+func findEnums(header string) (enums []enumType) {
+       for _, enum := range enumDefRe.FindAllStringSubmatch(header, -1) {
+               enums = append(enums, enumType{enum[2], 
enumValRe.FindAllString(enum[1], -1)})
+       }
+       return enums
+}
+
+func genEnum(out io.Writer, name string, values []string) {
+       doTemplate(out, []interface{}{name, values}, `{{$enumName := index . 
0}}{{$values := index . 1}}
+type {{mixedCase $enumName}} C.pn_{{$enumName}}_t
+const ({{range $values}}
+       {{mixedCase .}} {{mixedCase $enumName}} = C.{{.}} {{end}}
+)
+
+func (e {{mixedCase $enumName}}) String() string {
+       switch e {
+{{range $values}}
+       case C.{{.}}: return "{{mixedCaseTrim . "PN_"}}" {{end}}
+       }
+       return "unknown"
+}
+`)
+}
+
+var (
+       reSpace = regexp.MustCompile("\\s+")
+)
+
+func panicIf(err error) {
+       if err != nil {
+               panic(err)
+       }
+}
+
+func readHeader(name string) string {
+       file, err := os.Open(path.Join(*includeProton, name+".h"))
+       panicIf(err)
+       defer file.Close()
+       s, err := ioutil.ReadAll(file)
+       panicIf(err)
+       return string(s)
+}
+
+var copyright string = `/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+//
+// NOTE: This file was generated by genwrap.go, do not edit it by hand.
+//
+`
+
+type eventType struct {
+       // C, function and interface names for the event
+       Name, Cname, Fname, Iname string
+}
+
+func newEventType(cName string) eventType {
+       var etype eventType
+       etype.Cname = cName
+       etype.Name = mixedCaseTrim(cName, "PN_")
+       etype.Fname = "On" + etype.Name
+       etype.Iname = etype.Fname + "Interface"
+       return etype
+}
+
+var (
+       enumDefRe   = regexp.MustCompile("typedef enum {([^}]*)} 
pn_([a-z_]+)_t;")
+       enumValRe   = regexp.MustCompile("PN_[A-Z_]+")
+       skipEventRe = regexp.MustCompile("EVENT_NONE|REACTOR|SELECTABLE|TIMER")
+       skipFnRe    = 
regexp.MustCompile("attach|context|class|collect|^recv$|^send$|transport")
+)
+
+// Generate event wrappers.
+func event(out io.Writer) {
+       event_h := readHeader("event")
+
+       // Event is implented by hand in wrappers.go
+
+       // Get all the pn_event_type_t enum values
+       var etypes []eventType
+       enums := findEnums(event_h)
+       for _, e := range enums[0].Values {
+               if skipEventRe.FindStringSubmatch(e) == nil {
+                       etypes = append(etypes, newEventType(e))
+               }
+       }
+
+       doTemplate(out, etypes, `
+type EventType int
+const ({{range .}}
+        E{{.Name}} EventType = C.{{.Cname}}{{end}}
+)
+`)
+
+       doTemplate(out, etypes, `
+func (e EventType) String() string {
+       switch e {
+{{range .}}
+       case C.{{.Cname}}: return "{{.Name}}"{{end}}
+       }
+       return "Unknown"
+}
+`)
+}
+
+type genType struct {
+       Ctype, Gotype string
+       ToGo          func(value string) string
+       ToC           func(value string) string
+       Assign        func(value string) string
+}
+
+func (g genType) printBody(out io.Writer, value string) {
+       if g.Gotype != "" {
+               fmt.Fprintf(out, "return %s", g.ToGo(value))
+       } else {
+               fmt.Fprintf(out, "%s", value)
+       }
+}
+
+func (g genType) goLiteral(value string) string {
+       return fmt.Sprintf("%s{%s}", g.Gotype, value)
+}
+
+func (g genType) goConvert(value string) string {
+       switch g.Gotype {
+       case "string":
+               return fmt.Sprintf("C.GoString(%s)", value)
+       case "Event":
+               return fmt.Sprintf("makeEvent(%s)", value)
+       default:
+               return fmt.Sprintf("%s(%s)", g.Gotype, value)
+       }
+}
+
+var notStruct = map[string]bool{
+       "EventType":        true,
+       "SndSettleMode":    true,
+       "RcvSettleMode":    true,
+       "TerminusType":     true,
+       "State":            true,
+       "Durability":       true,
+       "ExpiryPolicy":     true,
+       "DistributionMode": true,
+}
+
+func mapType(ctype string) (g genType) {
+       g.Ctype = "C." + strings.Trim(ctype, " \n")
+
+       switch g.Ctype {
+       case "C.void":
+               g.Gotype = ""
+       case "C.size_t":
+               g.Gotype = "uint"
+       case "C.int":
+               g.Gotype = "int"
+       case "C.void *":
+               g.Gotype = "unsafe.Pointer"
+               g.Ctype = "unsafe.Pointer"
+       case "C.bool":
+               g.Gotype = "bool"
+       case "C.ssize_t":
+               g.Gotype = "int"
+       case "C.uint64_t":
+               g.Gotype = "uint64"
+       case "C.uint32_t":
+               g.Gotype = "uint16"
+       case "C.uint16_t":
+               g.Gotype = "uint32"
+       case "C.const char *":
+               fallthrough
+       case "C.char *":
+               g.Gotype = "string"
+               g.Ctype = "C.CString"
+               g.ToC = func(v string) string { return fmt.Sprintf("%sC", v) }
+               g.Assign = func(v string) string {
+                       return fmt.Sprintf("%sC := C.CString(%s)\n defer 
C.free(unsafe.Pointer(%sC))\n", v, v, v)
+               }
+       case "C.pn_seconds_t":
+               g.Gotype = "time.Duration"
+               g.ToGo = func(v string) string { return 
fmt.Sprintf("(time.Duration(%s) * time.Second)", v) }
+       case "C.pn_error_t *":
+               g.Gotype = "error"
+               g.ToGo = func(v string) string { return 
fmt.Sprintf("internal.PnError(unsafe.Pointer(%s))", v) }
+       default:
+               pnId := regexp.MustCompile(" *pn_([a-z_]+)_t *\\*? *")
+               match := pnId.FindStringSubmatch(g.Ctype)
+               if match == nil {
+                       panic(fmt.Errorf("unknown C type %#v", g.Ctype))
+               }
+               g.Gotype = mixedCase(match[1])
+               if !notStruct[g.Gotype] {
+                       g.ToGo = g.goLiteral
+                       g.ToC = func(v string) string { return v + ".pn" }
+               }
+       }
+       if g.ToGo == nil {
+               g.ToGo = g.goConvert // Use conversion by default.
+       }
+       if g.ToC == nil {
+               g.ToC = func(v string) string { return fmt.Sprintf("%s(%s)", 
g.Ctype, v) }
+       }
+       return
+}
+
+type genArg struct {
+       Name string
+       genType
+}
+
+var typeNameRe = regexp.MustCompile("^(.*( |\\*))([^ *]+)$")
+
+func splitArgs(argstr string) []genArg {
+       argstr = strings.Trim(argstr, " \n")
+       if argstr == "" {
+               return []genArg{}
+       }
+       args := make([]genArg, 0)
+       for _, item := range strings.Split(argstr, ",") {
+               item = strings.Trim(item, " \n")
+               typeName := typeNameRe.FindStringSubmatch(item)
+               if typeName == nil {
+                       panic(fmt.Errorf("Can't split argument type/name %#v", 
item))
+               }
+               cType := strings.Trim(typeName[1], " \n")
+               name := strings.Trim(typeName[3], " \n")
+               if name == "type" {
+                       name = "type_"
+               }
+               args = append(args, genArg{name, mapType(cType)})
+       }
+       return args
+}
+
+func goArgs(args []genArg) string {
+       l := ""
+       for i, arg := range args {
+               if i != 0 {
+                       l += ", "
+               }
+               l += arg.Name + " " + arg.Gotype
+       }
+       return l
+}
+
+func cArgs(args []genArg) string {
+       l := ""
+       for _, arg := range args {
+               l += fmt.Sprintf(", %s", arg.ToC(arg.Name))
+       }
+       return l
+}
+
+func cAssigns(args []genArg) string {
+       l := "\n"
+       for _, arg := range args {
+               if arg.Assign != nil {
+                       l += fmt.Sprintf("%s\n", arg.Assign(arg.Name))
+               }
+       }
+       return l
+}
+
+// Return the go name of the function or "" to skip the function.
+func goFnName(api, fname string) string {
+       // Skip class, context and attachment functions.
+       if skipFnRe.FindStringSubmatch(fname) != nil {
+               return ""
+       }
+       switch api + "." + fname {
+       case "link.get_drain":
+               return "IsDrain"
+       default:
+               return mixedCaseTrim(fname, "get_")
+       }
+}
+
+func apiWrapFns(api, header string, out io.Writer) {
+       fmt.Fprintf(out, "type %s struct{pn *C.pn_%s_t}\n", mixedCase(api), api)
+       fmt.Fprintf(out, "func (%c %s) IsNil() bool { return %c.pn == nil }\n", 
api[0], mixedCase(api), api[0])
+       fn := regexp.MustCompile(fmt.Sprintf(`PN_EXTERN ([a-z0-9_ ]+ *\*?) 
*pn_%s_([a-z_]+)\(pn_%s_t *\*[a-z_]+ *,? *([^)]*)\)`, api, api))
+       for _, m := range fn.FindAllStringSubmatch(header, -1) {
+               rtype, fname, argstr := mapType(m[1]), m[2], m[3]
+               gname := goFnName(api, fname)
+               if gname == "" { // Skip
+                       continue
+               }
+               args := splitArgs(argstr)
+               fmt.Fprintf(out, "func (%c %s) %s", api[0], mixedCase(api), 
gname)
+               fmt.Fprintf(out, "(%s) %s { ", goArgs(args), rtype.Gotype)
+               fmt.Fprint(out, cAssigns(args))
+               rtype.printBody(out, fmt.Sprintf("C.pn_%s_%s(%c.pn%s)", api, 
fname, api[0], cArgs(args)))
+               fmt.Fprintf(out, "}\n")
+       }
+}
+
+var includeProton = flag.String("include", "", "path to proton include files, 
including /proton")
+
+func main() {
+       flag.Parse()
+       outpath := "wrappers_gen.go"
+       out, err := os.Create(outpath)
+       panicIf(err)
+       defer out.Close()
+
+       apis := []string{"session", "link", "delivery", "disposition", 
"condition", "terminus", "connection"}
+       fmt.Fprintln(out, copyright)
+       fmt.Fprint(out, `
+package event
+
+import (
+       "time"
+  "unsafe"
+  "qpid.apache.org/proton/go/internal"
+)
+
+// #include <proton/types.h>
+// #include <proton/event.h>
+// #include <stdlib.h>
+`)
+       for _, api := range apis {
+               fmt.Fprintf(out, "// #include <proton/%s.h>\n", api)
+       }
+       fmt.Fprintln(out, `import "C"`)
+
+       event(out)
+
+       for _, api := range apis {
+               fmt.Fprintf(out, "// Wrappers for declarations in %s.h\n\n", 
api)
+               header := readHeader(api)
+               enums := findEnums(header)
+               for _, e := range enums {
+                       genEnum(out, e.Name, e.Values)
+               }
+               apiWrapFns(api, header, out)
+       }
+       out.Close()
+
+       // Run gofmt.
+       cmd := exec.Command("gofmt", "-w", outpath)
+       cmd.Stdout = os.Stdout
+       cmd.Stderr = os.Stderr
+       err = cmd.Run()
+       if err != nil {
+               fmt.Fprintf(os.Stderr, "gofmt: %s", err)
+               os.Exit(1)
+       }
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to