forked from mirror/go-json
Improve map encoding performance
This commit is contained in:
parent
de89bd3db6
commit
d8aa8348f4
|
@ -403,48 +403,41 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
b = appendStructHead(ctx, b)
|
b = appendStructHead(ctx, b)
|
||||||
iter := mapiterinit(code.Type, uptr)
|
mapCtx := encoder.NewMapContext(mlen)
|
||||||
ctx.KeepRefs = append(ctx.KeepRefs, iter)
|
mapiterinit(code.Type, uptr, &mapCtx.Iter)
|
||||||
store(ctxptr, code.ElemIdx, 0)
|
store(ctxptr, code.MapIter, uintptr(unsafe.Pointer(mapCtx)))
|
||||||
store(ctxptr, code.Length, uintptr(mlen))
|
ctx.KeepRefs = append(ctx.KeepRefs, unsafe.Pointer(mapCtx))
|
||||||
store(ctxptr, code.MapIter, uintptr(iter))
|
|
||||||
if (ctx.Option.Flag & encoder.UnorderedMapOption) != 0 {
|
if (ctx.Option.Flag & encoder.UnorderedMapOption) != 0 {
|
||||||
b = appendMapKeyIndent(ctx, code.Next, b)
|
b = appendMapKeyIndent(ctx, code.Next, b)
|
||||||
} else {
|
} else {
|
||||||
mapCtx := encoder.NewMapContext(mlen)
|
mapCtx.Start = len(b)
|
||||||
mapCtx.Pos = append(mapCtx.Pos, len(b))
|
mapCtx.First = len(b)
|
||||||
ctx.KeepRefs = append(ctx.KeepRefs, unsafe.Pointer(mapCtx))
|
|
||||||
store(ctxptr, code.End.MapPos, uintptr(unsafe.Pointer(mapCtx)))
|
|
||||||
}
|
}
|
||||||
key := mapiterkey(iter)
|
key := mapiterkey(&mapCtx.Iter)
|
||||||
store(ctxptr, code.Next.Idx, uintptr(key))
|
store(ctxptr, code.Next.Idx, uintptr(key))
|
||||||
code = code.Next
|
code = code.Next
|
||||||
case encoder.OpMapKey:
|
case encoder.OpMapKey:
|
||||||
idx := load(ctxptr, code.ElemIdx)
|
mapCtx := (*encoder.MapContext)(ptrToUnsafePtr(load(ctxptr, code.MapIter)))
|
||||||
length := load(ctxptr, code.Length)
|
idx := mapCtx.Idx
|
||||||
idx++
|
idx++
|
||||||
if (ctx.Option.Flag & encoder.UnorderedMapOption) != 0 {
|
if (ctx.Option.Flag & encoder.UnorderedMapOption) != 0 {
|
||||||
if idx < length {
|
if idx < mapCtx.Len {
|
||||||
b = appendMapKeyIndent(ctx, code, b)
|
b = appendMapKeyIndent(ctx, code, b)
|
||||||
store(ctxptr, code.ElemIdx, idx)
|
mapCtx.Idx = int(idx)
|
||||||
ptr := load(ctxptr, code.MapIter)
|
key := mapiterkey(&mapCtx.Iter)
|
||||||
iter := ptrToUnsafePtr(ptr)
|
|
||||||
key := mapiterkey(iter)
|
|
||||||
store(ctxptr, code.Next.Idx, uintptr(key))
|
store(ctxptr, code.Next.Idx, uintptr(key))
|
||||||
code = code.Next
|
code = code.Next
|
||||||
} else {
|
} else {
|
||||||
b = appendObjectEnd(ctx, code, b)
|
b = appendObjectEnd(ctx, code, b)
|
||||||
|
encoder.ReleaseMapContext(mapCtx)
|
||||||
code = code.End.Next
|
code = code.End.Next
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ptr := load(ctxptr, code.End.MapPos)
|
mapCtx.Slice.Items[mapCtx.Idx].Value = b[mapCtx.Start:len(b)]
|
||||||
mapCtx := (*encoder.MapContext)(ptrToUnsafePtr(ptr))
|
if idx < mapCtx.Len {
|
||||||
mapCtx.Pos = append(mapCtx.Pos, len(b))
|
mapCtx.Idx = int(idx)
|
||||||
if idx < length {
|
mapCtx.Start = len(b)
|
||||||
ptr := load(ctxptr, code.MapIter)
|
key := mapiterkey(&mapCtx.Iter)
|
||||||
iter := ptrToUnsafePtr(ptr)
|
|
||||||
store(ctxptr, code.ElemIdx, idx)
|
|
||||||
key := mapiterkey(iter)
|
|
||||||
store(ctxptr, code.Next.Idx, uintptr(key))
|
store(ctxptr, code.Next.Idx, uintptr(key))
|
||||||
code = code.Next
|
code = code.Next
|
||||||
} else {
|
} else {
|
||||||
|
@ -452,46 +445,27 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case encoder.OpMapValue:
|
case encoder.OpMapValue:
|
||||||
|
mapCtx := (*encoder.MapContext)(ptrToUnsafePtr(load(ctxptr, code.MapIter)))
|
||||||
if (ctx.Option.Flag & encoder.UnorderedMapOption) != 0 {
|
if (ctx.Option.Flag & encoder.UnorderedMapOption) != 0 {
|
||||||
b = appendColon(ctx, b)
|
b = appendColon(ctx, b)
|
||||||
} else {
|
} else {
|
||||||
ptr := load(ctxptr, code.End.MapPos)
|
mapCtx.Slice.Items[mapCtx.Idx].Key = b[mapCtx.Start:len(b)]
|
||||||
mapCtx := (*encoder.MapContext)(ptrToUnsafePtr(ptr))
|
mapCtx.Start = len(b)
|
||||||
mapCtx.Pos = append(mapCtx.Pos, len(b))
|
|
||||||
}
|
}
|
||||||
ptr := load(ctxptr, code.MapIter)
|
value := mapitervalue(&mapCtx.Iter)
|
||||||
iter := ptrToUnsafePtr(ptr)
|
|
||||||
value := mapitervalue(iter)
|
|
||||||
store(ctxptr, code.Next.Idx, uintptr(value))
|
store(ctxptr, code.Next.Idx, uintptr(value))
|
||||||
mapiternext(iter)
|
mapiternext(&mapCtx.Iter)
|
||||||
code = code.Next
|
code = code.Next
|
||||||
case encoder.OpMapEnd:
|
case encoder.OpMapEnd:
|
||||||
// this operation only used by sorted map.
|
// this operation only used by sorted map.
|
||||||
length := int(load(ctxptr, code.Length))
|
mapCtx := (*encoder.MapContext)(ptrToUnsafePtr(load(ctxptr, code.MapIter)))
|
||||||
ptr := load(ctxptr, code.MapPos)
|
|
||||||
mapCtx := (*encoder.MapContext)(ptrToUnsafePtr(ptr))
|
|
||||||
pos := mapCtx.Pos
|
|
||||||
for i := 0; i < length; i++ {
|
|
||||||
startKey := pos[i*2]
|
|
||||||
startValue := pos[i*2+1]
|
|
||||||
var endValue int
|
|
||||||
if i+1 < length {
|
|
||||||
endValue = pos[i*2+2]
|
|
||||||
} else {
|
|
||||||
endValue = len(b)
|
|
||||||
}
|
|
||||||
mapCtx.Slice.Items = append(mapCtx.Slice.Items, encoder.MapItem{
|
|
||||||
Key: b[startKey:startValue],
|
|
||||||
Value: b[startValue:endValue],
|
|
||||||
})
|
|
||||||
}
|
|
||||||
sort.Sort(mapCtx.Slice)
|
sort.Sort(mapCtx.Slice)
|
||||||
buf := mapCtx.Buf
|
buf := mapCtx.Buf
|
||||||
for _, item := range mapCtx.Slice.Items {
|
for _, item := range mapCtx.Slice.Items {
|
||||||
buf = appendMapKeyValue(ctx, code, buf, item.Key, item.Value)
|
buf = appendMapKeyValue(ctx, code, buf, item.Key, item.Value)
|
||||||
}
|
}
|
||||||
buf = appendMapEnd(ctx, code, buf)
|
buf = appendMapEnd(ctx, code, buf)
|
||||||
b = b[:pos[0]]
|
b = b[:mapCtx.First]
|
||||||
b = append(b, buf...)
|
b = append(b, buf...)
|
||||||
mapCtx.Buf = buf
|
mapCtx.Buf = buf
|
||||||
encoder.ReleaseMapContext(mapCtx)
|
encoder.ReleaseMapContext(mapCtx)
|
||||||
|
|
|
@ -207,7 +207,7 @@ type MapItem struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type Mapslice struct {
|
type Mapslice struct {
|
||||||
Items []MapItem
|
Items []*MapItem
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Mapslice) Len() int {
|
func (m *Mapslice) Len() int {
|
||||||
|
@ -222,10 +222,32 @@ func (m *Mapslice) Swap(i, j int) {
|
||||||
m.Items[i], m.Items[j] = m.Items[j], m.Items[i]
|
m.Items[i], m.Items[j] = m.Items[j], m.Items[i]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type mapIter struct {
|
||||||
|
key unsafe.Pointer
|
||||||
|
elem unsafe.Pointer
|
||||||
|
t unsafe.Pointer
|
||||||
|
h unsafe.Pointer
|
||||||
|
buckets unsafe.Pointer
|
||||||
|
bptr unsafe.Pointer
|
||||||
|
overflow unsafe.Pointer
|
||||||
|
oldoverflow unsafe.Pointer
|
||||||
|
startBucket uintptr
|
||||||
|
offset uint8
|
||||||
|
wrapped bool
|
||||||
|
B uint8
|
||||||
|
i uint8
|
||||||
|
bucket uintptr
|
||||||
|
checkBucket uintptr
|
||||||
|
}
|
||||||
|
|
||||||
type MapContext struct {
|
type MapContext struct {
|
||||||
Pos []int
|
Start int
|
||||||
|
First int
|
||||||
|
Idx int
|
||||||
Slice *Mapslice
|
Slice *Mapslice
|
||||||
Buf []byte
|
Buf []byte
|
||||||
|
Len int
|
||||||
|
Iter mapIter
|
||||||
}
|
}
|
||||||
|
|
||||||
var mapContextPool = sync.Pool{
|
var mapContextPool = sync.Pool{
|
||||||
|
@ -238,17 +260,21 @@ func NewMapContext(mapLen int) *MapContext {
|
||||||
ctx := mapContextPool.Get().(*MapContext)
|
ctx := mapContextPool.Get().(*MapContext)
|
||||||
if ctx.Slice == nil {
|
if ctx.Slice == nil {
|
||||||
ctx.Slice = &Mapslice{
|
ctx.Slice = &Mapslice{
|
||||||
Items: make([]MapItem, 0, mapLen),
|
Items: make([]*MapItem, 0, mapLen),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if cap(ctx.Pos) < (mapLen*2 + 1) {
|
if len(ctx.Slice.Items) < mapLen {
|
||||||
ctx.Pos = make([]int, 0, mapLen*2+1)
|
ctx.Slice.Items = make([]*MapItem, mapLen)
|
||||||
ctx.Slice.Items = make([]MapItem, 0, mapLen)
|
for i := 0; i < mapLen; i++ {
|
||||||
|
ctx.Slice.Items[i] = &MapItem{}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
ctx.Pos = ctx.Pos[:0]
|
ctx.Slice.Items = ctx.Slice.Items[:mapLen]
|
||||||
ctx.Slice.Items = ctx.Slice.Items[:0]
|
|
||||||
}
|
}
|
||||||
ctx.Buf = ctx.Buf[:0]
|
ctx.Buf = ctx.Buf[:0]
|
||||||
|
ctx.Iter = mapIter{}
|
||||||
|
ctx.Idx = 0
|
||||||
|
ctx.Len = mapLen
|
||||||
return ctx
|
return ctx
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -256,17 +282,17 @@ func ReleaseMapContext(c *MapContext) {
|
||||||
mapContextPool.Put(c)
|
mapContextPool.Put(c)
|
||||||
}
|
}
|
||||||
|
|
||||||
//go:linkname MapIterInit reflect.mapiterinit
|
//go:linkname MapIterInit runtime.mapiterinit
|
||||||
//go:noescape
|
//go:noescape
|
||||||
func MapIterInit(mapType *runtime.Type, m unsafe.Pointer) unsafe.Pointer
|
func MapIterInit(mapType *runtime.Type, m unsafe.Pointer, it *mapIter)
|
||||||
|
|
||||||
//go:linkname MapIterKey reflect.mapiterkey
|
//go:linkname MapIterKey reflect.mapiterkey
|
||||||
//go:noescape
|
//go:noescape
|
||||||
func MapIterKey(it unsafe.Pointer) unsafe.Pointer
|
func MapIterKey(it *mapIter) unsafe.Pointer
|
||||||
|
|
||||||
//go:linkname MapIterNext reflect.mapiternext
|
//go:linkname MapIterNext reflect.mapiternext
|
||||||
//go:noescape
|
//go:noescape
|
||||||
func MapIterNext(it unsafe.Pointer)
|
func MapIterNext(it *mapIter)
|
||||||
|
|
||||||
//go:linkname MapLen reflect.maplen
|
//go:linkname MapLen reflect.maplen
|
||||||
//go:noescape
|
//go:noescape
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
//go:build !go1.13
|
||||||
// +build !go1.13
|
// +build !go1.13
|
||||||
|
|
||||||
package encoder
|
package encoder
|
||||||
|
@ -5,4 +6,4 @@ package encoder
|
||||||
import "unsafe"
|
import "unsafe"
|
||||||
|
|
||||||
//go:linkname MapIterValue reflect.mapitervalue
|
//go:linkname MapIterValue reflect.mapitervalue
|
||||||
func MapIterValue(it unsafe.Pointer) unsafe.Pointer
|
func MapIterValue(it *mapIter) unsafe.Pointer
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
//go:build go1.13
|
||||||
// +build go1.13
|
// +build go1.13
|
||||||
|
|
||||||
package encoder
|
package encoder
|
||||||
|
@ -5,4 +6,4 @@ package encoder
|
||||||
import "unsafe"
|
import "unsafe"
|
||||||
|
|
||||||
//go:linkname MapIterValue reflect.mapiterelem
|
//go:linkname MapIterValue reflect.mapiterelem
|
||||||
func MapIterValue(it unsafe.Pointer) unsafe.Pointer
|
func MapIterValue(it *mapIter) unsafe.Pointer
|
||||||
|
|
|
@ -685,6 +685,7 @@ func newMapEndCode(ctx *compileContext, typ *runtime.Type, head *Opcode) *Opcode
|
||||||
Length: head.Length,
|
Length: head.Length,
|
||||||
MapPos: mapPos,
|
MapPos: mapPos,
|
||||||
Indent: ctx.indent,
|
Indent: ctx.indent,
|
||||||
|
MapIter: head.MapIter,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -403,48 +403,41 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
b = appendStructHead(ctx, b)
|
b = appendStructHead(ctx, b)
|
||||||
iter := mapiterinit(code.Type, uptr)
|
mapCtx := encoder.NewMapContext(mlen)
|
||||||
ctx.KeepRefs = append(ctx.KeepRefs, iter)
|
mapiterinit(code.Type, uptr, &mapCtx.Iter)
|
||||||
store(ctxptr, code.ElemIdx, 0)
|
store(ctxptr, code.MapIter, uintptr(unsafe.Pointer(mapCtx)))
|
||||||
store(ctxptr, code.Length, uintptr(mlen))
|
ctx.KeepRefs = append(ctx.KeepRefs, unsafe.Pointer(mapCtx))
|
||||||
store(ctxptr, code.MapIter, uintptr(iter))
|
|
||||||
if (ctx.Option.Flag & encoder.UnorderedMapOption) != 0 {
|
if (ctx.Option.Flag & encoder.UnorderedMapOption) != 0 {
|
||||||
b = appendMapKeyIndent(ctx, code.Next, b)
|
b = appendMapKeyIndent(ctx, code.Next, b)
|
||||||
} else {
|
} else {
|
||||||
mapCtx := encoder.NewMapContext(mlen)
|
mapCtx.Start = len(b)
|
||||||
mapCtx.Pos = append(mapCtx.Pos, len(b))
|
mapCtx.First = len(b)
|
||||||
ctx.KeepRefs = append(ctx.KeepRefs, unsafe.Pointer(mapCtx))
|
|
||||||
store(ctxptr, code.End.MapPos, uintptr(unsafe.Pointer(mapCtx)))
|
|
||||||
}
|
}
|
||||||
key := mapiterkey(iter)
|
key := mapiterkey(&mapCtx.Iter)
|
||||||
store(ctxptr, code.Next.Idx, uintptr(key))
|
store(ctxptr, code.Next.Idx, uintptr(key))
|
||||||
code = code.Next
|
code = code.Next
|
||||||
case encoder.OpMapKey:
|
case encoder.OpMapKey:
|
||||||
idx := load(ctxptr, code.ElemIdx)
|
mapCtx := (*encoder.MapContext)(ptrToUnsafePtr(load(ctxptr, code.MapIter)))
|
||||||
length := load(ctxptr, code.Length)
|
idx := mapCtx.Idx
|
||||||
idx++
|
idx++
|
||||||
if (ctx.Option.Flag & encoder.UnorderedMapOption) != 0 {
|
if (ctx.Option.Flag & encoder.UnorderedMapOption) != 0 {
|
||||||
if idx < length {
|
if idx < mapCtx.Len {
|
||||||
b = appendMapKeyIndent(ctx, code, b)
|
b = appendMapKeyIndent(ctx, code, b)
|
||||||
store(ctxptr, code.ElemIdx, idx)
|
mapCtx.Idx = int(idx)
|
||||||
ptr := load(ctxptr, code.MapIter)
|
key := mapiterkey(&mapCtx.Iter)
|
||||||
iter := ptrToUnsafePtr(ptr)
|
|
||||||
key := mapiterkey(iter)
|
|
||||||
store(ctxptr, code.Next.Idx, uintptr(key))
|
store(ctxptr, code.Next.Idx, uintptr(key))
|
||||||
code = code.Next
|
code = code.Next
|
||||||
} else {
|
} else {
|
||||||
b = appendObjectEnd(ctx, code, b)
|
b = appendObjectEnd(ctx, code, b)
|
||||||
|
encoder.ReleaseMapContext(mapCtx)
|
||||||
code = code.End.Next
|
code = code.End.Next
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ptr := load(ctxptr, code.End.MapPos)
|
mapCtx.Slice.Items[mapCtx.Idx].Value = b[mapCtx.Start:len(b)]
|
||||||
mapCtx := (*encoder.MapContext)(ptrToUnsafePtr(ptr))
|
if idx < mapCtx.Len {
|
||||||
mapCtx.Pos = append(mapCtx.Pos, len(b))
|
mapCtx.Idx = int(idx)
|
||||||
if idx < length {
|
mapCtx.Start = len(b)
|
||||||
ptr := load(ctxptr, code.MapIter)
|
key := mapiterkey(&mapCtx.Iter)
|
||||||
iter := ptrToUnsafePtr(ptr)
|
|
||||||
store(ctxptr, code.ElemIdx, idx)
|
|
||||||
key := mapiterkey(iter)
|
|
||||||
store(ctxptr, code.Next.Idx, uintptr(key))
|
store(ctxptr, code.Next.Idx, uintptr(key))
|
||||||
code = code.Next
|
code = code.Next
|
||||||
} else {
|
} else {
|
||||||
|
@ -452,46 +445,27 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case encoder.OpMapValue:
|
case encoder.OpMapValue:
|
||||||
|
mapCtx := (*encoder.MapContext)(ptrToUnsafePtr(load(ctxptr, code.MapIter)))
|
||||||
if (ctx.Option.Flag & encoder.UnorderedMapOption) != 0 {
|
if (ctx.Option.Flag & encoder.UnorderedMapOption) != 0 {
|
||||||
b = appendColon(ctx, b)
|
b = appendColon(ctx, b)
|
||||||
} else {
|
} else {
|
||||||
ptr := load(ctxptr, code.End.MapPos)
|
mapCtx.Slice.Items[mapCtx.Idx].Key = b[mapCtx.Start:len(b)]
|
||||||
mapCtx := (*encoder.MapContext)(ptrToUnsafePtr(ptr))
|
mapCtx.Start = len(b)
|
||||||
mapCtx.Pos = append(mapCtx.Pos, len(b))
|
|
||||||
}
|
}
|
||||||
ptr := load(ctxptr, code.MapIter)
|
value := mapitervalue(&mapCtx.Iter)
|
||||||
iter := ptrToUnsafePtr(ptr)
|
|
||||||
value := mapitervalue(iter)
|
|
||||||
store(ctxptr, code.Next.Idx, uintptr(value))
|
store(ctxptr, code.Next.Idx, uintptr(value))
|
||||||
mapiternext(iter)
|
mapiternext(&mapCtx.Iter)
|
||||||
code = code.Next
|
code = code.Next
|
||||||
case encoder.OpMapEnd:
|
case encoder.OpMapEnd:
|
||||||
// this operation only used by sorted map.
|
// this operation only used by sorted map.
|
||||||
length := int(load(ctxptr, code.Length))
|
mapCtx := (*encoder.MapContext)(ptrToUnsafePtr(load(ctxptr, code.MapIter)))
|
||||||
ptr := load(ctxptr, code.MapPos)
|
|
||||||
mapCtx := (*encoder.MapContext)(ptrToUnsafePtr(ptr))
|
|
||||||
pos := mapCtx.Pos
|
|
||||||
for i := 0; i < length; i++ {
|
|
||||||
startKey := pos[i*2]
|
|
||||||
startValue := pos[i*2+1]
|
|
||||||
var endValue int
|
|
||||||
if i+1 < length {
|
|
||||||
endValue = pos[i*2+2]
|
|
||||||
} else {
|
|
||||||
endValue = len(b)
|
|
||||||
}
|
|
||||||
mapCtx.Slice.Items = append(mapCtx.Slice.Items, encoder.MapItem{
|
|
||||||
Key: b[startKey:startValue],
|
|
||||||
Value: b[startValue:endValue],
|
|
||||||
})
|
|
||||||
}
|
|
||||||
sort.Sort(mapCtx.Slice)
|
sort.Sort(mapCtx.Slice)
|
||||||
buf := mapCtx.Buf
|
buf := mapCtx.Buf
|
||||||
for _, item := range mapCtx.Slice.Items {
|
for _, item := range mapCtx.Slice.Items {
|
||||||
buf = appendMapKeyValue(ctx, code, buf, item.Key, item.Value)
|
buf = appendMapKeyValue(ctx, code, buf, item.Key, item.Value)
|
||||||
}
|
}
|
||||||
buf = appendMapEnd(ctx, code, buf)
|
buf = appendMapEnd(ctx, code, buf)
|
||||||
b = b[:pos[0]]
|
b = b[:mapCtx.First]
|
||||||
b = append(b, buf...)
|
b = append(b, buf...)
|
||||||
mapCtx.Buf = buf
|
mapCtx.Buf = buf
|
||||||
encoder.ReleaseMapContext(mapCtx)
|
encoder.ReleaseMapContext(mapCtx)
|
||||||
|
|
|
@ -403,48 +403,41 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
b = appendStructHead(ctx, b)
|
b = appendStructHead(ctx, b)
|
||||||
iter := mapiterinit(code.Type, uptr)
|
mapCtx := encoder.NewMapContext(mlen)
|
||||||
ctx.KeepRefs = append(ctx.KeepRefs, iter)
|
mapiterinit(code.Type, uptr, &mapCtx.Iter)
|
||||||
store(ctxptr, code.ElemIdx, 0)
|
store(ctxptr, code.MapIter, uintptr(unsafe.Pointer(mapCtx)))
|
||||||
store(ctxptr, code.Length, uintptr(mlen))
|
ctx.KeepRefs = append(ctx.KeepRefs, unsafe.Pointer(mapCtx))
|
||||||
store(ctxptr, code.MapIter, uintptr(iter))
|
|
||||||
if (ctx.Option.Flag & encoder.UnorderedMapOption) != 0 {
|
if (ctx.Option.Flag & encoder.UnorderedMapOption) != 0 {
|
||||||
b = appendMapKeyIndent(ctx, code.Next, b)
|
b = appendMapKeyIndent(ctx, code.Next, b)
|
||||||
} else {
|
} else {
|
||||||
mapCtx := encoder.NewMapContext(mlen)
|
mapCtx.Start = len(b)
|
||||||
mapCtx.Pos = append(mapCtx.Pos, len(b))
|
mapCtx.First = len(b)
|
||||||
ctx.KeepRefs = append(ctx.KeepRefs, unsafe.Pointer(mapCtx))
|
|
||||||
store(ctxptr, code.End.MapPos, uintptr(unsafe.Pointer(mapCtx)))
|
|
||||||
}
|
}
|
||||||
key := mapiterkey(iter)
|
key := mapiterkey(&mapCtx.Iter)
|
||||||
store(ctxptr, code.Next.Idx, uintptr(key))
|
store(ctxptr, code.Next.Idx, uintptr(key))
|
||||||
code = code.Next
|
code = code.Next
|
||||||
case encoder.OpMapKey:
|
case encoder.OpMapKey:
|
||||||
idx := load(ctxptr, code.ElemIdx)
|
mapCtx := (*encoder.MapContext)(ptrToUnsafePtr(load(ctxptr, code.MapIter)))
|
||||||
length := load(ctxptr, code.Length)
|
idx := mapCtx.Idx
|
||||||
idx++
|
idx++
|
||||||
if (ctx.Option.Flag & encoder.UnorderedMapOption) != 0 {
|
if (ctx.Option.Flag & encoder.UnorderedMapOption) != 0 {
|
||||||
if idx < length {
|
if idx < mapCtx.Len {
|
||||||
b = appendMapKeyIndent(ctx, code, b)
|
b = appendMapKeyIndent(ctx, code, b)
|
||||||
store(ctxptr, code.ElemIdx, idx)
|
mapCtx.Idx = int(idx)
|
||||||
ptr := load(ctxptr, code.MapIter)
|
key := mapiterkey(&mapCtx.Iter)
|
||||||
iter := ptrToUnsafePtr(ptr)
|
|
||||||
key := mapiterkey(iter)
|
|
||||||
store(ctxptr, code.Next.Idx, uintptr(key))
|
store(ctxptr, code.Next.Idx, uintptr(key))
|
||||||
code = code.Next
|
code = code.Next
|
||||||
} else {
|
} else {
|
||||||
b = appendObjectEnd(ctx, code, b)
|
b = appendObjectEnd(ctx, code, b)
|
||||||
|
encoder.ReleaseMapContext(mapCtx)
|
||||||
code = code.End.Next
|
code = code.End.Next
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ptr := load(ctxptr, code.End.MapPos)
|
mapCtx.Slice.Items[mapCtx.Idx].Value = b[mapCtx.Start:len(b)]
|
||||||
mapCtx := (*encoder.MapContext)(ptrToUnsafePtr(ptr))
|
if idx < mapCtx.Len {
|
||||||
mapCtx.Pos = append(mapCtx.Pos, len(b))
|
mapCtx.Idx = int(idx)
|
||||||
if idx < length {
|
mapCtx.Start = len(b)
|
||||||
ptr := load(ctxptr, code.MapIter)
|
key := mapiterkey(&mapCtx.Iter)
|
||||||
iter := ptrToUnsafePtr(ptr)
|
|
||||||
store(ctxptr, code.ElemIdx, idx)
|
|
||||||
key := mapiterkey(iter)
|
|
||||||
store(ctxptr, code.Next.Idx, uintptr(key))
|
store(ctxptr, code.Next.Idx, uintptr(key))
|
||||||
code = code.Next
|
code = code.Next
|
||||||
} else {
|
} else {
|
||||||
|
@ -452,46 +445,27 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case encoder.OpMapValue:
|
case encoder.OpMapValue:
|
||||||
|
mapCtx := (*encoder.MapContext)(ptrToUnsafePtr(load(ctxptr, code.MapIter)))
|
||||||
if (ctx.Option.Flag & encoder.UnorderedMapOption) != 0 {
|
if (ctx.Option.Flag & encoder.UnorderedMapOption) != 0 {
|
||||||
b = appendColon(ctx, b)
|
b = appendColon(ctx, b)
|
||||||
} else {
|
} else {
|
||||||
ptr := load(ctxptr, code.End.MapPos)
|
mapCtx.Slice.Items[mapCtx.Idx].Key = b[mapCtx.Start:len(b)]
|
||||||
mapCtx := (*encoder.MapContext)(ptrToUnsafePtr(ptr))
|
mapCtx.Start = len(b)
|
||||||
mapCtx.Pos = append(mapCtx.Pos, len(b))
|
|
||||||
}
|
}
|
||||||
ptr := load(ctxptr, code.MapIter)
|
value := mapitervalue(&mapCtx.Iter)
|
||||||
iter := ptrToUnsafePtr(ptr)
|
|
||||||
value := mapitervalue(iter)
|
|
||||||
store(ctxptr, code.Next.Idx, uintptr(value))
|
store(ctxptr, code.Next.Idx, uintptr(value))
|
||||||
mapiternext(iter)
|
mapiternext(&mapCtx.Iter)
|
||||||
code = code.Next
|
code = code.Next
|
||||||
case encoder.OpMapEnd:
|
case encoder.OpMapEnd:
|
||||||
// this operation only used by sorted map.
|
// this operation only used by sorted map.
|
||||||
length := int(load(ctxptr, code.Length))
|
mapCtx := (*encoder.MapContext)(ptrToUnsafePtr(load(ctxptr, code.MapIter)))
|
||||||
ptr := load(ctxptr, code.MapPos)
|
|
||||||
mapCtx := (*encoder.MapContext)(ptrToUnsafePtr(ptr))
|
|
||||||
pos := mapCtx.Pos
|
|
||||||
for i := 0; i < length; i++ {
|
|
||||||
startKey := pos[i*2]
|
|
||||||
startValue := pos[i*2+1]
|
|
||||||
var endValue int
|
|
||||||
if i+1 < length {
|
|
||||||
endValue = pos[i*2+2]
|
|
||||||
} else {
|
|
||||||
endValue = len(b)
|
|
||||||
}
|
|
||||||
mapCtx.Slice.Items = append(mapCtx.Slice.Items, encoder.MapItem{
|
|
||||||
Key: b[startKey:startValue],
|
|
||||||
Value: b[startValue:endValue],
|
|
||||||
})
|
|
||||||
}
|
|
||||||
sort.Sort(mapCtx.Slice)
|
sort.Sort(mapCtx.Slice)
|
||||||
buf := mapCtx.Buf
|
buf := mapCtx.Buf
|
||||||
for _, item := range mapCtx.Slice.Items {
|
for _, item := range mapCtx.Slice.Items {
|
||||||
buf = appendMapKeyValue(ctx, code, buf, item.Key, item.Value)
|
buf = appendMapKeyValue(ctx, code, buf, item.Key, item.Value)
|
||||||
}
|
}
|
||||||
buf = appendMapEnd(ctx, code, buf)
|
buf = appendMapEnd(ctx, code, buf)
|
||||||
b = b[:pos[0]]
|
b = b[:mapCtx.First]
|
||||||
b = append(b, buf...)
|
b = append(b, buf...)
|
||||||
mapCtx.Buf = buf
|
mapCtx.Buf = buf
|
||||||
encoder.ReleaseMapContext(mapCtx)
|
encoder.ReleaseMapContext(mapCtx)
|
||||||
|
|
|
@ -403,48 +403,41 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
b = appendStructHead(ctx, b)
|
b = appendStructHead(ctx, b)
|
||||||
iter := mapiterinit(code.Type, uptr)
|
mapCtx := encoder.NewMapContext(mlen)
|
||||||
ctx.KeepRefs = append(ctx.KeepRefs, iter)
|
mapiterinit(code.Type, uptr, &mapCtx.Iter)
|
||||||
store(ctxptr, code.ElemIdx, 0)
|
store(ctxptr, code.MapIter, uintptr(unsafe.Pointer(mapCtx)))
|
||||||
store(ctxptr, code.Length, uintptr(mlen))
|
ctx.KeepRefs = append(ctx.KeepRefs, unsafe.Pointer(mapCtx))
|
||||||
store(ctxptr, code.MapIter, uintptr(iter))
|
|
||||||
if (ctx.Option.Flag & encoder.UnorderedMapOption) != 0 {
|
if (ctx.Option.Flag & encoder.UnorderedMapOption) != 0 {
|
||||||
b = appendMapKeyIndent(ctx, code.Next, b)
|
b = appendMapKeyIndent(ctx, code.Next, b)
|
||||||
} else {
|
} else {
|
||||||
mapCtx := encoder.NewMapContext(mlen)
|
mapCtx.Start = len(b)
|
||||||
mapCtx.Pos = append(mapCtx.Pos, len(b))
|
mapCtx.First = len(b)
|
||||||
ctx.KeepRefs = append(ctx.KeepRefs, unsafe.Pointer(mapCtx))
|
|
||||||
store(ctxptr, code.End.MapPos, uintptr(unsafe.Pointer(mapCtx)))
|
|
||||||
}
|
}
|
||||||
key := mapiterkey(iter)
|
key := mapiterkey(&mapCtx.Iter)
|
||||||
store(ctxptr, code.Next.Idx, uintptr(key))
|
store(ctxptr, code.Next.Idx, uintptr(key))
|
||||||
code = code.Next
|
code = code.Next
|
||||||
case encoder.OpMapKey:
|
case encoder.OpMapKey:
|
||||||
idx := load(ctxptr, code.ElemIdx)
|
mapCtx := (*encoder.MapContext)(ptrToUnsafePtr(load(ctxptr, code.MapIter)))
|
||||||
length := load(ctxptr, code.Length)
|
idx := mapCtx.Idx
|
||||||
idx++
|
idx++
|
||||||
if (ctx.Option.Flag & encoder.UnorderedMapOption) != 0 {
|
if (ctx.Option.Flag & encoder.UnorderedMapOption) != 0 {
|
||||||
if idx < length {
|
if idx < mapCtx.Len {
|
||||||
b = appendMapKeyIndent(ctx, code, b)
|
b = appendMapKeyIndent(ctx, code, b)
|
||||||
store(ctxptr, code.ElemIdx, idx)
|
mapCtx.Idx = int(idx)
|
||||||
ptr := load(ctxptr, code.MapIter)
|
key := mapiterkey(&mapCtx.Iter)
|
||||||
iter := ptrToUnsafePtr(ptr)
|
|
||||||
key := mapiterkey(iter)
|
|
||||||
store(ctxptr, code.Next.Idx, uintptr(key))
|
store(ctxptr, code.Next.Idx, uintptr(key))
|
||||||
code = code.Next
|
code = code.Next
|
||||||
} else {
|
} else {
|
||||||
b = appendObjectEnd(ctx, code, b)
|
b = appendObjectEnd(ctx, code, b)
|
||||||
|
encoder.ReleaseMapContext(mapCtx)
|
||||||
code = code.End.Next
|
code = code.End.Next
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ptr := load(ctxptr, code.End.MapPos)
|
mapCtx.Slice.Items[mapCtx.Idx].Value = b[mapCtx.Start:len(b)]
|
||||||
mapCtx := (*encoder.MapContext)(ptrToUnsafePtr(ptr))
|
if idx < mapCtx.Len {
|
||||||
mapCtx.Pos = append(mapCtx.Pos, len(b))
|
mapCtx.Idx = int(idx)
|
||||||
if idx < length {
|
mapCtx.Start = len(b)
|
||||||
ptr := load(ctxptr, code.MapIter)
|
key := mapiterkey(&mapCtx.Iter)
|
||||||
iter := ptrToUnsafePtr(ptr)
|
|
||||||
store(ctxptr, code.ElemIdx, idx)
|
|
||||||
key := mapiterkey(iter)
|
|
||||||
store(ctxptr, code.Next.Idx, uintptr(key))
|
store(ctxptr, code.Next.Idx, uintptr(key))
|
||||||
code = code.Next
|
code = code.Next
|
||||||
} else {
|
} else {
|
||||||
|
@ -452,46 +445,27 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case encoder.OpMapValue:
|
case encoder.OpMapValue:
|
||||||
|
mapCtx := (*encoder.MapContext)(ptrToUnsafePtr(load(ctxptr, code.MapIter)))
|
||||||
if (ctx.Option.Flag & encoder.UnorderedMapOption) != 0 {
|
if (ctx.Option.Flag & encoder.UnorderedMapOption) != 0 {
|
||||||
b = appendColon(ctx, b)
|
b = appendColon(ctx, b)
|
||||||
} else {
|
} else {
|
||||||
ptr := load(ctxptr, code.End.MapPos)
|
mapCtx.Slice.Items[mapCtx.Idx].Key = b[mapCtx.Start:len(b)]
|
||||||
mapCtx := (*encoder.MapContext)(ptrToUnsafePtr(ptr))
|
mapCtx.Start = len(b)
|
||||||
mapCtx.Pos = append(mapCtx.Pos, len(b))
|
|
||||||
}
|
}
|
||||||
ptr := load(ctxptr, code.MapIter)
|
value := mapitervalue(&mapCtx.Iter)
|
||||||
iter := ptrToUnsafePtr(ptr)
|
|
||||||
value := mapitervalue(iter)
|
|
||||||
store(ctxptr, code.Next.Idx, uintptr(value))
|
store(ctxptr, code.Next.Idx, uintptr(value))
|
||||||
mapiternext(iter)
|
mapiternext(&mapCtx.Iter)
|
||||||
code = code.Next
|
code = code.Next
|
||||||
case encoder.OpMapEnd:
|
case encoder.OpMapEnd:
|
||||||
// this operation only used by sorted map.
|
// this operation only used by sorted map.
|
||||||
length := int(load(ctxptr, code.Length))
|
mapCtx := (*encoder.MapContext)(ptrToUnsafePtr(load(ctxptr, code.MapIter)))
|
||||||
ptr := load(ctxptr, code.MapPos)
|
|
||||||
mapCtx := (*encoder.MapContext)(ptrToUnsafePtr(ptr))
|
|
||||||
pos := mapCtx.Pos
|
|
||||||
for i := 0; i < length; i++ {
|
|
||||||
startKey := pos[i*2]
|
|
||||||
startValue := pos[i*2+1]
|
|
||||||
var endValue int
|
|
||||||
if i+1 < length {
|
|
||||||
endValue = pos[i*2+2]
|
|
||||||
} else {
|
|
||||||
endValue = len(b)
|
|
||||||
}
|
|
||||||
mapCtx.Slice.Items = append(mapCtx.Slice.Items, encoder.MapItem{
|
|
||||||
Key: b[startKey:startValue],
|
|
||||||
Value: b[startValue:endValue],
|
|
||||||
})
|
|
||||||
}
|
|
||||||
sort.Sort(mapCtx.Slice)
|
sort.Sort(mapCtx.Slice)
|
||||||
buf := mapCtx.Buf
|
buf := mapCtx.Buf
|
||||||
for _, item := range mapCtx.Slice.Items {
|
for _, item := range mapCtx.Slice.Items {
|
||||||
buf = appendMapKeyValue(ctx, code, buf, item.Key, item.Value)
|
buf = appendMapKeyValue(ctx, code, buf, item.Key, item.Value)
|
||||||
}
|
}
|
||||||
buf = appendMapEnd(ctx, code, buf)
|
buf = appendMapEnd(ctx, code, buf)
|
||||||
b = b[:pos[0]]
|
b = b[:mapCtx.First]
|
||||||
b = append(b, buf...)
|
b = append(b, buf...)
|
||||||
mapCtx.Buf = buf
|
mapCtx.Buf = buf
|
||||||
encoder.ReleaseMapContext(mapCtx)
|
encoder.ReleaseMapContext(mapCtx)
|
||||||
|
|
|
@ -403,48 +403,41 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
b = appendStructHead(ctx, b)
|
b = appendStructHead(ctx, b)
|
||||||
iter := mapiterinit(code.Type, uptr)
|
mapCtx := encoder.NewMapContext(mlen)
|
||||||
ctx.KeepRefs = append(ctx.KeepRefs, iter)
|
mapiterinit(code.Type, uptr, &mapCtx.Iter)
|
||||||
store(ctxptr, code.ElemIdx, 0)
|
store(ctxptr, code.MapIter, uintptr(unsafe.Pointer(mapCtx)))
|
||||||
store(ctxptr, code.Length, uintptr(mlen))
|
ctx.KeepRefs = append(ctx.KeepRefs, unsafe.Pointer(mapCtx))
|
||||||
store(ctxptr, code.MapIter, uintptr(iter))
|
|
||||||
if (ctx.Option.Flag & encoder.UnorderedMapOption) != 0 {
|
if (ctx.Option.Flag & encoder.UnorderedMapOption) != 0 {
|
||||||
b = appendMapKeyIndent(ctx, code.Next, b)
|
b = appendMapKeyIndent(ctx, code.Next, b)
|
||||||
} else {
|
} else {
|
||||||
mapCtx := encoder.NewMapContext(mlen)
|
mapCtx.Start = len(b)
|
||||||
mapCtx.Pos = append(mapCtx.Pos, len(b))
|
mapCtx.First = len(b)
|
||||||
ctx.KeepRefs = append(ctx.KeepRefs, unsafe.Pointer(mapCtx))
|
|
||||||
store(ctxptr, code.End.MapPos, uintptr(unsafe.Pointer(mapCtx)))
|
|
||||||
}
|
}
|
||||||
key := mapiterkey(iter)
|
key := mapiterkey(&mapCtx.Iter)
|
||||||
store(ctxptr, code.Next.Idx, uintptr(key))
|
store(ctxptr, code.Next.Idx, uintptr(key))
|
||||||
code = code.Next
|
code = code.Next
|
||||||
case encoder.OpMapKey:
|
case encoder.OpMapKey:
|
||||||
idx := load(ctxptr, code.ElemIdx)
|
mapCtx := (*encoder.MapContext)(ptrToUnsafePtr(load(ctxptr, code.MapIter)))
|
||||||
length := load(ctxptr, code.Length)
|
idx := mapCtx.Idx
|
||||||
idx++
|
idx++
|
||||||
if (ctx.Option.Flag & encoder.UnorderedMapOption) != 0 {
|
if (ctx.Option.Flag & encoder.UnorderedMapOption) != 0 {
|
||||||
if idx < length {
|
if idx < mapCtx.Len {
|
||||||
b = appendMapKeyIndent(ctx, code, b)
|
b = appendMapKeyIndent(ctx, code, b)
|
||||||
store(ctxptr, code.ElemIdx, idx)
|
mapCtx.Idx = int(idx)
|
||||||
ptr := load(ctxptr, code.MapIter)
|
key := mapiterkey(&mapCtx.Iter)
|
||||||
iter := ptrToUnsafePtr(ptr)
|
|
||||||
key := mapiterkey(iter)
|
|
||||||
store(ctxptr, code.Next.Idx, uintptr(key))
|
store(ctxptr, code.Next.Idx, uintptr(key))
|
||||||
code = code.Next
|
code = code.Next
|
||||||
} else {
|
} else {
|
||||||
b = appendObjectEnd(ctx, code, b)
|
b = appendObjectEnd(ctx, code, b)
|
||||||
|
encoder.ReleaseMapContext(mapCtx)
|
||||||
code = code.End.Next
|
code = code.End.Next
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ptr := load(ctxptr, code.End.MapPos)
|
mapCtx.Slice.Items[mapCtx.Idx].Value = b[mapCtx.Start:len(b)]
|
||||||
mapCtx := (*encoder.MapContext)(ptrToUnsafePtr(ptr))
|
if idx < mapCtx.Len {
|
||||||
mapCtx.Pos = append(mapCtx.Pos, len(b))
|
mapCtx.Idx = int(idx)
|
||||||
if idx < length {
|
mapCtx.Start = len(b)
|
||||||
ptr := load(ctxptr, code.MapIter)
|
key := mapiterkey(&mapCtx.Iter)
|
||||||
iter := ptrToUnsafePtr(ptr)
|
|
||||||
store(ctxptr, code.ElemIdx, idx)
|
|
||||||
key := mapiterkey(iter)
|
|
||||||
store(ctxptr, code.Next.Idx, uintptr(key))
|
store(ctxptr, code.Next.Idx, uintptr(key))
|
||||||
code = code.Next
|
code = code.Next
|
||||||
} else {
|
} else {
|
||||||
|
@ -452,46 +445,27 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case encoder.OpMapValue:
|
case encoder.OpMapValue:
|
||||||
|
mapCtx := (*encoder.MapContext)(ptrToUnsafePtr(load(ctxptr, code.MapIter)))
|
||||||
if (ctx.Option.Flag & encoder.UnorderedMapOption) != 0 {
|
if (ctx.Option.Flag & encoder.UnorderedMapOption) != 0 {
|
||||||
b = appendColon(ctx, b)
|
b = appendColon(ctx, b)
|
||||||
} else {
|
} else {
|
||||||
ptr := load(ctxptr, code.End.MapPos)
|
mapCtx.Slice.Items[mapCtx.Idx].Key = b[mapCtx.Start:len(b)]
|
||||||
mapCtx := (*encoder.MapContext)(ptrToUnsafePtr(ptr))
|
mapCtx.Start = len(b)
|
||||||
mapCtx.Pos = append(mapCtx.Pos, len(b))
|
|
||||||
}
|
}
|
||||||
ptr := load(ctxptr, code.MapIter)
|
value := mapitervalue(&mapCtx.Iter)
|
||||||
iter := ptrToUnsafePtr(ptr)
|
|
||||||
value := mapitervalue(iter)
|
|
||||||
store(ctxptr, code.Next.Idx, uintptr(value))
|
store(ctxptr, code.Next.Idx, uintptr(value))
|
||||||
mapiternext(iter)
|
mapiternext(&mapCtx.Iter)
|
||||||
code = code.Next
|
code = code.Next
|
||||||
case encoder.OpMapEnd:
|
case encoder.OpMapEnd:
|
||||||
// this operation only used by sorted map.
|
// this operation only used by sorted map.
|
||||||
length := int(load(ctxptr, code.Length))
|
mapCtx := (*encoder.MapContext)(ptrToUnsafePtr(load(ctxptr, code.MapIter)))
|
||||||
ptr := load(ctxptr, code.MapPos)
|
|
||||||
mapCtx := (*encoder.MapContext)(ptrToUnsafePtr(ptr))
|
|
||||||
pos := mapCtx.Pos
|
|
||||||
for i := 0; i < length; i++ {
|
|
||||||
startKey := pos[i*2]
|
|
||||||
startValue := pos[i*2+1]
|
|
||||||
var endValue int
|
|
||||||
if i+1 < length {
|
|
||||||
endValue = pos[i*2+2]
|
|
||||||
} else {
|
|
||||||
endValue = len(b)
|
|
||||||
}
|
|
||||||
mapCtx.Slice.Items = append(mapCtx.Slice.Items, encoder.MapItem{
|
|
||||||
Key: b[startKey:startValue],
|
|
||||||
Value: b[startValue:endValue],
|
|
||||||
})
|
|
||||||
}
|
|
||||||
sort.Sort(mapCtx.Slice)
|
sort.Sort(mapCtx.Slice)
|
||||||
buf := mapCtx.Buf
|
buf := mapCtx.Buf
|
||||||
for _, item := range mapCtx.Slice.Items {
|
for _, item := range mapCtx.Slice.Items {
|
||||||
buf = appendMapKeyValue(ctx, code, buf, item.Key, item.Value)
|
buf = appendMapKeyValue(ctx, code, buf, item.Key, item.Value)
|
||||||
}
|
}
|
||||||
buf = appendMapEnd(ctx, code, buf)
|
buf = appendMapEnd(ctx, code, buf)
|
||||||
b = b[:pos[0]]
|
b = b[:mapCtx.First]
|
||||||
b = append(b, buf...)
|
b = append(b, buf...)
|
||||||
mapCtx.Buf = buf
|
mapCtx.Buf = buf
|
||||||
encoder.ReleaseMapContext(mapCtx)
|
encoder.ReleaseMapContext(mapCtx)
|
||||||
|
|
Loading…
Reference in New Issue