// context is a structure storing details of a particular code generation task
type context struct {
inputFile string // file with input JSON data
- inputBuff *bytes.Buffer // contents of the input file
+ inputData []byte // contents of the input file
+ inputBuff *bytes.Buffer // contents of the input file currently being read
inputLine int // currently processed line in the input file
outputFile string // file with output data
packageName string // name of the Go package being generated
return err
}
// read the file
- inputData, err := readFile(inputFile)
+ ctx.inputData, err = readFile(inputFile)
if err != nil {
return err
}
- ctx.inputBuff = bytes.NewBuffer(inputData)
// parse JSON
- jsonRoot, err := parseJSON(inputData)
+ jsonRoot, err := parseJSON(ctx.inputData)
if err != nil {
return err
}
generatePackageHeader(ctx, w, jsonRoot)
// generate data types
+ ctx.inputBuff = bytes.NewBuffer(ctx.inputData)
+ ctx.inputLine = 0
ctx.types = make(map[string]string)
types := jsonRoot.Map("types")
for i := 0; i < types.Len(); i++ {
}
// generate messages
+ ctx.inputBuff = bytes.NewBuffer(ctx.inputData)
+ ctx.inputLine = 0
messages := jsonRoot.Map("messages")
for i := 0; i < messages.Len(); i++ {
msg := messages.At(i)
// print out the source of the generated message - the JSON
msgFound := false
+ msgTitle := "\"" + msgName + "\","
+ var msgIndent int
for {
lineBuff, err := ctx.inputBuff.ReadBytes('\n')
if err != nil {
line := string(lineBuff)
if !msgFound {
- if strings.Contains(line, msgName) {
- fmt.Fprintf(w, "// Generated from '%s', line %d:\n", ctx.inputFile, ctx.inputLine)
- fmt.Fprintln(w, "//")
- fmt.Fprint(w, "//", line)
- msgFound = true
+ msgIndent = strings.Index(line, msgTitle)
+ if msgIndent > -1 {
+ prefix := line[:msgIndent]
+ suffix := line[msgIndent+len(msgTitle):]
+ // If no other non-whitespace character then we are at the message header.
+ if strings.IndexFunc(prefix, isNotSpace) == -1 && strings.IndexFunc(suffix, isNotSpace) == -1 {
+ fmt.Fprintf(w, "// Generated from '%s', line %d:\n", ctx.inputFile, ctx.inputLine)
+ fmt.Fprintln(w, "//")
+ fmt.Fprint(w, "//", line)
+ msgFound = true
+ }
}
} else {
- fmt.Fprint(w, "//", line)
- if len(strings.Trim(line, " ")) < 4 {
+ if strings.IndexFunc(line, isNotSpace) < msgIndent {
break // end of the message in JSON
}
+ fmt.Fprint(w, "//", line)
}
}
fmt.Fprintln(w, "//")
return string(runes)
}
+// isNotSpace returns true if the rune is NOT a whitespace character.
+func isNotSpace(r rune) bool {
+ return !unicode.IsSpace(r)
+}
+
// commonInitialisms is a set of common initialisms that need to stay in upper case.
var commonInitialisms = map[string]bool{
"ACL": true,