Commit 1f1bf04d authored by Kirill Smelkov's avatar Kirill Smelkov

.

parent a37720fa
This diff is collapsed.
...@@ -230,9 +230,11 @@ type CodecCodeGen interface { ...@@ -230,9 +230,11 @@ type CodecCodeGen interface {
// for not function this is generated code needed for resultExpr() // for not function this is generated code needed for resultExpr()
generatedCode() string generatedCode() string
/*
// get result expression // get result expression
// this is result of computations for not top-level code XXX // this is result of computations for not top-level code XXX
resultExpr() string resultExpr() string
*/
} }
// common part of codegenerators // common part of codegenerators
...@@ -283,10 +285,18 @@ func (s *size) AddExpr(format string, a ...interface{}) { ...@@ -283,10 +285,18 @@ func (s *size) AddExpr(format string, a ...interface{}) {
} }
func (s *size) String() string { func (s *size) String() string {
sizeStr := fmt.Sprintf("%v", s.num) // num + expr1 + expr2 + ... (ommiting what is possible)
sizev := []string{}
if s.num != 0 {
sizev = append(sizev, fmt.Sprintf("%v", s.num))
}
exprStr := s.ExprString() exprStr := s.ExprString()
if exprStr != "" { if exprStr != "" {
sizeStr += " + " + exprStr sizev = append(sizev, exprStr)
}
sizeStr := strings.Join(sizev, " + ")
if sizeStr == "" {
sizeStr = "0"
} }
return sizeStr return sizeStr
} }
...@@ -295,6 +305,10 @@ func (s *size) ExprString() string { ...@@ -295,6 +305,10 @@ func (s *size) ExprString() string {
return strings.Join(s.exprv, " + ") return strings.Join(s.exprv, " + ")
} }
func (s *size) IsZero() bool {
return s.num == 0 && len(s.exprv) == 0
}
// sizer generates code to compute endoded size of a packet // sizer generates code to compute endoded size of a packet
type sizer struct { type sizer struct {
...@@ -314,8 +328,16 @@ type encoder struct { ...@@ -314,8 +328,16 @@ type encoder struct {
// decoder generates code to decode a packet // decoder generates code to decode a packet
type decoder struct { type decoder struct {
Buffer // buffer for generated code // buffers for generated code
n int // current decode position in data // current delayed overflow check will be inserted in between buf & bufCur
buf Buffer
bufCur Buffer
// current decode position in data.
// also = currently collected info for delayed emit of overflow check
// .num - position
// .exprv - XXX TODO
pos size
commonCoder commonCoder
} }
...@@ -361,10 +383,6 @@ func (s *sizer) generatedCode() string { ...@@ -361,10 +383,6 @@ func (s *sizer) generatedCode() string {
return code.String() return code.String()
} }
func (e *encoder) resultExpr() string {
panic("should not be called (?)") // XXX
}
func (e *encoder) generatedCode() string { func (e *encoder) generatedCode() string {
code := Buffer{} code := Buffer{}
// prologue // prologue
...@@ -380,11 +398,24 @@ func (e *encoder) generatedCode() string { ...@@ -380,11 +398,24 @@ func (e *encoder) generatedCode() string {
return code.String() return code.String()
} }
func (d *decoder) resultExpr() string { // XXX place?
panic("should not be called (?)") // XXX func (d *decoder) emit(format string, a ...interface{}) {
d.bufCur.emit(format, a...)
}
// XXX place?
func (d *decoder) flushOverflow() {
if !d.pos.IsZero() {
d.buf.emit("if uint32(len(data)) < %v { goto overflow }", &d.pos)
}
d.buf.Write(d.bufCur.Bytes())
d.bufCur.Reset()
// TODO
} }
func (d *decoder) generatedCode() string { func (d *decoder) generatedCode() string {
d.flushOverflow()
code := Buffer{} code := Buffer{}
// prologue // prologue
if d.recvName != "" { if d.recvName != "" {
...@@ -394,10 +425,10 @@ func (d *decoder) generatedCode() string { ...@@ -394,10 +425,10 @@ func (d *decoder) generatedCode() string {
code.emit("var %v uint32", d.var__("nread")) code.emit("var %v uint32", d.var__("nread"))
} }
code.Write(d.Bytes()) // XXX -> d.buf.Bytes() ? code.Write(d.buf.Bytes())
// epilogue // epilogue
retexpr := fmt.Sprintf("%v", d.n) retexpr := fmt.Sprintf("%v", d.pos.num)
if d.varUsed["nread"] { if d.varUsed["nread"] {
retexpr += fmt.Sprintf(" + int(%v)", d.var__("nread")) retexpr += fmt.Sprintf(" + int(%v)", d.var__("nread"))
} }
...@@ -434,10 +465,10 @@ func (e *encoder) genBasic(path string, typ *types.Basic, userType types.Type) { ...@@ -434,10 +465,10 @@ func (e *encoder) genBasic(path string, typ *types.Basic, userType types.Type) {
func (d *decoder) genBasic(assignto string, typ *types.Basic, userType types.Type) { func (d *decoder) genBasic(assignto string, typ *types.Basic, userType types.Type) {
basic := basicTypes[typ.Kind()] basic := basicTypes[typ.Kind()]
d.emit("if len(data) < %v { goto overflow }", d.n + basic.wireSize) //d.emit("if len(data) < %v { goto overflow }", d.n + basic.wireSize)
dataptr := fmt.Sprintf("data[%v:]", d.n) dataptr := fmt.Sprintf("data[%v:]", d.pos.num)
decoded := fmt.Sprintf(basic.decode, dataptr) decoded := fmt.Sprintf(basic.decode, dataptr)
d.n += basic.wireSize d.pos.Add(basic.wireSize)
if userType != nil && userType != typ { if userType != nil && userType != typ {
// userType is a named type over some basic, like // userType is a named type over some basic, like
// type ClusterState int32 // type ClusterState int32
...@@ -472,13 +503,17 @@ func (e *encoder) genStrBytes(path string) { ...@@ -472,13 +503,17 @@ func (e *encoder) genStrBytes(path string) {
func (d *decoder) genStrBytes(assignto string) { func (d *decoder) genStrBytes(assignto string) {
d.emit("{") d.emit("{")
d.genBasic("l:", types.Typ[types.Uint32], nil) d.genBasic("l:", types.Typ[types.Uint32], nil)
d.emit("data = data[%v:]", d.n) d.emit("data = data[%v:]", d.pos.num)
d.emit("if uint32(len(data)) < l { goto overflow }") d.emit("%v += %v + l", d.var_("nread"), d.pos.num)
//d.emit("if uint32(len(data)) < l { goto overflow }")
d.flushOverflow()
d.pos = size{} // zero
d.pos.AddExpr("l")
d.emit("%v= string(data[:l])", assignto) d.emit("%v= string(data[:l])", assignto)
d.emit("data = data[l:]") d.emit("data = data[l:]")
d.emit("%v += %v + l", d.var_("nread"), d.n)
d.emit("}") d.emit("}")
d.n = 0
} }
// emit code to encode/decode slice // emit code to encode/decode slice
...@@ -540,9 +575,12 @@ func (e *encoder) genSlice(path string, typ *types.Slice, obj types.Object) { ...@@ -540,9 +575,12 @@ func (e *encoder) genSlice(path string, typ *types.Slice, obj types.Object) {
func (d *decoder) genSlice(assignto string, typ *types.Slice, obj types.Object) { func (d *decoder) genSlice(assignto string, typ *types.Slice, obj types.Object) {
d.emit("{") d.emit("{")
d.genBasic("l:", types.Typ[types.Uint32], nil) d.genBasic("l:", types.Typ[types.Uint32], nil)
d.emit("data = data[%v:]", d.n) d.emit("data = data[%v:]", d.pos.num)
d.emit("%v += %v", d.var_("nread"), d.n) d.emit("%v += %v", d.var_("nread"), d.pos.num)
d.n = 0
d.flushOverflow()
d.pos = size{} // zero
d.pos.AddExpr("l")
/* /*
elemSize, elemFixed := typeSizeFixed(typ.Elem()) elemSize, elemFixed := typeSizeFixed(typ.Elem())
...@@ -557,13 +595,22 @@ func (d *decoder) genSlice(assignto string, typ *types.Slice, obj types.Object) ...@@ -557,13 +595,22 @@ func (d *decoder) genSlice(assignto string, typ *types.Slice, obj types.Object)
d.emit("%v= make(%v, l)", assignto, typeName(typ)) d.emit("%v= make(%v, l)", assignto, typeName(typ))
d.emit("for i := 0; uint32(i) < l; i++ {") d.emit("for i := 0; uint32(i) < l; i++ {")
d.emit("a := &%s[i]", assignto) d.emit("a := &%s[i]", assignto)
d.flushOverflow()
d.pos = size{} // zero
codegenType("(*a)", typ.Elem(), obj, d) codegenType("(*a)", typ.Elem(), obj, d)
d.emit("data = data[%v:]", d.n) // FIXME wrt slice of slice ?
d.emit("%v += %v", d.var_("nread"), d.n)
d.emit("data = data[%v:]", d.pos.num) // FIXME wrt slice of slice ?
d.emit("%v += %v", d.var_("nread"), d.pos.num)
d.emit("}") d.emit("}")
d.flushOverflow()
d.pos = size{} // zero
//d.emit("%v= string(data[:l])", assignto) //d.emit("%v= string(data[:l])", assignto)
d.emit("}") d.emit("}")
d.n = 0 //d.n = 0
} }
// generate code to encode/decode map // generate code to encode/decode map
...@@ -628,15 +675,22 @@ func (e *encoder) genMap(path string, typ *types.Map, obj types.Object) { ...@@ -628,15 +675,22 @@ func (e *encoder) genMap(path string, typ *types.Map, obj types.Object) {
func (d *decoder) genMap(assignto string, typ *types.Map, obj types.Object) { func (d *decoder) genMap(assignto string, typ *types.Map, obj types.Object) {
d.emit("{") d.emit("{")
d.genBasic("l:", types.Typ[types.Uint32], nil) d.genBasic("l:", types.Typ[types.Uint32], nil)
d.emit("data = data[%v:]", d.n) d.emit("data = data[%v:]", d.pos.num)
d.emit("%v += %v", d.var_("nread"), d.n) d.emit("%v += %v", d.var_("nread"), d.pos.num)
d.n = 0
d.flushOverflow()
d.pos = size{} // zero
d.pos.AddExpr("l")
d.emit("%v= make(%v, l)", assignto, typeName(typ)) d.emit("%v= make(%v, l)", assignto, typeName(typ))
// TODO size check // TODO size check
// TODO if size(item)==const - check l in one go // TODO if size(item)==const - check l in one go
//d.emit("if len(data) < l { goto overflow }") //d.emit("if len(data) < l { goto overflow }")
d.emit("m := %v", assignto) d.emit("m := %v", assignto)
d.emit("for i := 0; uint32(i) < l; i++ {") d.emit("for i := 0; uint32(i) < l; i++ {")
d.flushOverflow()
d.pos = size{} // zero
codegenType("key:", typ.Key(), obj, d) codegenType("key:", typ.Key(), obj, d)
switch typ.Elem().Underlying().(type) { switch typ.Elem().Underlying().(type) {
...@@ -652,12 +706,15 @@ func (d *decoder) genMap(assignto string, typ *types.Map, obj types.Object) { ...@@ -652,12 +706,15 @@ func (d *decoder) genMap(assignto string, typ *types.Map, obj types.Object) {
d.emit("m[key] = v") d.emit("m[key] = v")
} }
d.emit("data = data[%v:]", d.n) // FIXME wrt map of map ? d.emit("data = data[%v:]", d.pos.num) // FIXME wrt map of map ?
d.emit("%v += %v", d.var_("nread"), d.n) d.emit("%v += %v", d.var_("nread"), d.pos.num)
d.emit("}") d.emit("}")
d.flushOverflow()
d.pos = size{} // zero
//d.emit("%v= string(data[:l])", assignto) //d.emit("%v= string(data[:l])", assignto)
d.emit("}") d.emit("}")
d.n = 0
} }
// top-level driver for emitting encode/decode code for a type // top-level driver for emitting encode/decode code for a type
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment