github.com/robotn/xgb@v0.0.0-20190912153532-2cb92d044934/xgbgen/go_list.go (about) 1 package main 2 3 import ( 4 "fmt" 5 "log" 6 "strings" 7 ) 8 9 // List fields 10 func (f *ListField) Define(c *Context) { 11 c.Putln("%s %s // size: %s", 12 f.SrcName(), f.SrcType(), f.Size()) 13 } 14 15 func (f *ListField) Read(c *Context, prefix string) { 16 switch t := f.Type.(type) { 17 case *Resource: 18 length := f.LengthExpr.Reduce(prefix) 19 c.Putln("%s%s = make([]%s, %s)", 20 prefix, f.SrcName(), t.SrcName(), length) 21 c.Putln("for i := 0; i < int(%s); i++ {", length) 22 ReadSimpleSingleField(c, fmt.Sprintf("%s%s[i]", prefix, f.SrcName()), t) 23 c.Putln("}") 24 case *Base: 25 length := f.LengthExpr.Reduce(prefix) 26 if strings.ToLower(t.XmlName()) == "char" { 27 c.Putln("{") 28 c.Putln("byteString := make([]%s, %s)", t.SrcName(), length) 29 c.Putln("copy(byteString[:%s], buf[b:])", length) 30 c.Putln("%s%s = string(byteString)", prefix, f.SrcName()) 31 // This is apparently a special case. The "Str" type itself 32 // doesn't specify any padding. I suppose it's up to the 33 // request/reply spec that uses it to get the padding right? 34 c.Putln("b += int(%s)", length) 35 c.Putln("}") 36 } else if t.SrcName() == "byte" { 37 c.Putln("%s%s = make([]%s, %s)", 38 prefix, f.SrcName(), t.SrcName(), length) 39 c.Putln("copy(%s%s[:%s], buf[b:])", prefix, f.SrcName(), length) 40 c.Putln("b += int(%s)", length) 41 } else { 42 c.Putln("%s%s = make([]%s, %s)", 43 prefix, f.SrcName(), t.SrcName(), length) 44 c.Putln("for i := 0; i < int(%s); i++ {", length) 45 ReadSimpleSingleField(c, 46 fmt.Sprintf("%s%s[i]", prefix, f.SrcName()), t) 47 c.Putln("}") 48 } 49 case *TypeDef: 50 length := f.LengthExpr.Reduce(prefix) 51 c.Putln("%s%s = make([]%s, %s)", 52 prefix, f.SrcName(), t.SrcName(), length) 53 c.Putln("for i := 0; i < int(%s); i++ {", length) 54 ReadSimpleSingleField(c, fmt.Sprintf("%s%s[i]", prefix, f.SrcName()), t) 55 c.Putln("}") 56 case *Union: 57 c.Putln("%s%s = make([]%s, %s)", 58 prefix, f.SrcName(), t.SrcName(), f.LengthExpr.Reduce(prefix)) 59 c.Putln("b += %sReadList(buf[b:], %s%s)", 60 t.SrcName(), prefix, f.SrcName()) 61 case *Struct: 62 c.Putln("%s%s = make([]%s, %s)", 63 prefix, f.SrcName(), t.SrcName(), f.LengthExpr.Reduce(prefix)) 64 c.Putln("b += %sReadList(buf[b:], %s%s)", 65 t.SrcName(), prefix, f.SrcName()) 66 default: 67 log.Panicf("Cannot read list field '%s' with %T type.", 68 f.XmlName(), f.Type) 69 } 70 } 71 72 func (f *ListField) Write(c *Context, prefix string) { 73 switch t := f.Type.(type) { 74 case *Resource: 75 length := f.Length().Reduce(prefix) 76 c.Putln("for i := 0; i < int(%s); i++ {", length) 77 WriteSimpleSingleField(c, 78 fmt.Sprintf("%s%s[i]", prefix, f.SrcName()), t) 79 c.Putln("}") 80 case *Base: 81 length := f.Length().Reduce(prefix) 82 if t.SrcName() == "byte" { 83 c.Putln("copy(buf[b:], %s%s[:%s])", prefix, f.SrcName(), length) 84 c.Putln("b += int(%s)", length) 85 } else { 86 c.Putln("for i := 0; i < int(%s); i++ {", length) 87 WriteSimpleSingleField(c, 88 fmt.Sprintf("%s%s[i]", prefix, f.SrcName()), t) 89 c.Putln("}") 90 } 91 case *TypeDef: 92 length := f.Length().Reduce(prefix) 93 c.Putln("for i := 0; i < int(%s); i++ {", length) 94 WriteSimpleSingleField(c, 95 fmt.Sprintf("%s%s[i]", prefix, f.SrcName()), t) 96 c.Putln("}") 97 case *Union: 98 c.Putln("b += %sListBytes(buf[b:], %s%s)", 99 t.SrcName(), prefix, f.SrcName()) 100 case *Struct: 101 c.Putln("b += %sListBytes(buf[b:], %s%s)", 102 t.SrcName(), prefix, f.SrcName()) 103 default: 104 log.Panicf("Cannot write list field '%s' with %T type.", 105 f.XmlName(), f.Type) 106 } 107 }