diff --git a/encode.go b/encode.go index 54e7150..5cce9ad 100644 --- a/encode.go +++ b/encode.go @@ -3,6 +3,7 @@ package json import ( "bytes" "encoding" + "encoding/base64" "io" "math" "reflect" @@ -310,6 +311,22 @@ func (e *Encoder) encodeString(s string) { } } +func (e *Encoder) encodeByteSlice(b []byte) { + encodedLen := base64.StdEncoding.EncodedLen(len(b)) + e.encodeByte('"') + pos := len(e.buf) + remainLen := cap(e.buf[pos:]) + var buf []byte + if remainLen > encodedLen { + buf = e.buf[pos : pos+encodedLen] + } else { + buf = make([]byte, encodedLen) + } + base64.StdEncoding.Encode(buf, b) + e.encodeBytes(buf) + e.encodeByte('"') +} + func (e *Encoder) encodeByte(b byte) { e.buf = append(e.buf, b) } diff --git a/encode_vm.go b/encode_vm.go index 8578965..9780a03 100644 --- a/encode_vm.go +++ b/encode_vm.go @@ -99,13 +99,7 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error { if ptr == 0 || header.Data == 0 { e.encodeNull() } else { - b := e.ptrToBytes(ptr) - encodedLen := base64.StdEncoding.EncodedLen(len(b)) - e.encodeByte('"') - buf := make([]byte, encodedLen) - base64.StdEncoding.Encode(buf, b) - e.encodeBytes(buf) - e.encodeByte('"') + e.encodeByteSlice(e.ptrToBytes(ptr)) } code = code.next case opInterface: @@ -1151,10 +1145,7 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error { } else { e.encodeByte('{') e.encodeBytes(code.key) - s := base64.StdEncoding.EncodeToString(e.ptrToBytes(ptr + code.offset)) - e.encodeByte('"') - e.encodeBytes(*(*[]byte)(unsafe.Pointer(&s))) - e.encodeByte('"') + e.encodeByteSlice(e.ptrToBytes(ptr + code.offset)) code = code.next } case opStructFieldPtrAnonymousHeadBytes: @@ -1166,10 +1157,7 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error { code = code.end } else { e.encodeBytes(code.key) - s := base64.StdEncoding.EncodeToString(e.ptrToBytes(ptr + code.offset)) - e.encodeByte('"') - e.encodeBytes(*(*[]byte)(unsafe.Pointer(&s))) - e.encodeByte('"') + e.encodeByteSlice(e.ptrToBytes(ptr + code.offset)) code = code.next } case opStructFieldPtrHeadArray: @@ -2347,10 +2335,7 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error { code = code.nextField } else { e.encodeBytes(code.key) - s := base64.StdEncoding.EncodeToString(v) - e.encodeByte('"') - e.encodeBytes(*(*[]byte)(unsafe.Pointer(&s))) - e.encodeByte('"') + e.encodeByteSlice(v) code = code.next } } @@ -2370,10 +2355,7 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error { code = code.nextField } else { e.encodeBytes(code.key) - s := base64.StdEncoding.EncodeToString(v) - e.encodeByte('"') - e.encodeBytes(*(*[]byte)(unsafe.Pointer(&s))) - e.encodeByte('"') + e.encodeByteSlice(v) code = code.next } } @@ -3459,12 +3441,7 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error { } else { e.encodeByte('{') e.encodeBytes(code.key) - s := base64.StdEncoding.EncodeToString( - e.ptrToBytes(ptr + code.offset), - ) - e.encodeByte('"') - e.encodeBytes(*(*[]byte)(unsafe.Pointer(&s))) - e.encodeByte('"') + e.encodeByteSlice(e.ptrToBytes(ptr + code.offset)) code = code.next } case opStructFieldPtrAnonymousHeadStringTagBytes: @@ -3479,12 +3456,7 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error { code = code.end.next } else { e.encodeBytes(code.key) - s := base64.StdEncoding.EncodeToString( - e.ptrToBytes(ptr + code.offset), - ) - e.encodeByte('"') - e.encodeBytes(*(*[]byte)(unsafe.Pointer(&s))) - e.encodeByte('"') + e.encodeByteSlice(e.ptrToBytes(ptr + code.offset)) code = code.next } case opStructFieldPtrHeadStringTagMarshalJSON: @@ -4088,10 +4060,7 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error { } ptr := load(ctxptr, code.headIdx) e.encodeBytes(code.key) - s := base64.StdEncoding.EncodeToString(e.ptrToBytes(ptr + code.offset)) - e.encodeByte('"') - e.encodeBytes(*(*[]byte)(unsafe.Pointer(&s))) - e.encodeByte('"') + e.encodeByteSlice(e.ptrToBytes(ptr + code.offset)) code = code.next case opStructFieldMarshalJSON: if e.buf[len(e.buf)-1] != '{' { @@ -4659,10 +4628,7 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error { e.encodeByte(',') } e.encodeBytes(code.key) - s := base64.StdEncoding.EncodeToString(v) - e.encodeByte('"') - e.encodeBytes(*(*[]byte)(unsafe.Pointer(&s))) - e.encodeByte('"') + e.encodeByteSlice(v) } code = code.next case opStructFieldOmitEmptyMarshalJSON: @@ -5211,10 +5177,7 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error { e.encodeByte(',') } e.encodeBytes(code.key) - s := base64.StdEncoding.EncodeToString(v) - e.encodeByte('"') - e.encodeBytes(*(*[]byte)(unsafe.Pointer(&s))) - e.encodeByte('"') + e.encodeByteSlice(v) code = code.next case opStructFieldStringTagMarshalJSON: ptr := load(ctxptr, code.headIdx)