2
* Copyright 2021 ByteDance Inc.
4
* Licensed under the Apache License, Version 2.0 (the "License");
5
* you may not use this file except in compliance with the License.
6
* You may obtain a copy of the License at
8
* http://www.apache.org/licenses/LICENSE-2.0
10
* Unless required by applicable law or agreed to in writing, software
11
* distributed under the License is distributed on an "AS IS" BASIS,
12
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
* See the License for the specific language governing permissions and
14
* limitations under the License.
25
"github.com/bytedance/sonic/internal/native"
26
"github.com/bytedance/sonic/internal/rt"
30
k string // when the map key is integer, k is pointed to m
35
type _MapIterator struct {
36
it rt.GoMapIterator // must be the first field
37
kv rt.GoSlice // slice of _MapPair
42
iteratorPool = sync.Pool{}
43
iteratorPair = rt.UnpackType(reflect.TypeOf(_MapPair{}))
47
if unsafe.Offsetof(_MapIterator{}.it) != 0 {
48
panic("_MapIterator.it is not the first field")
53
func newIterator() *_MapIterator {
54
if v := iteratorPool.Get(); v == nil {
55
return new(_MapIterator)
57
return resetIterator(v.(*_MapIterator))
61
func resetIterator(p *_MapIterator) *_MapIterator {
63
p.it = rt.GoMapIterator{}
68
func (self *_MapIterator) at(i int) *_MapPair {
69
return (*_MapPair)(unsafe.Pointer(uintptr(self.kv.Ptr) + uintptr(i) * unsafe.Sizeof(_MapPair{})))
72
func (self *_MapIterator) add() (p *_MapPair) {
73
p = self.at(self.kv.Len)
78
func (self *_MapIterator) data() (p []_MapPair) {
79
*(*rt.GoSlice)(unsafe.Pointer(&p)) = self.kv
83
func (self *_MapIterator) append(t *rt.GoType, k unsafe.Pointer, v unsafe.Pointer) (err error) {
87
/* check for strings */
88
if tk := t.Kind(); tk != reflect.String {
89
return self.appendGeneric(p, t, tk, k)
92
/* fast path for strings */
97
func (self *_MapIterator) appendGeneric(p *_MapPair, t *rt.GoType, v reflect.Kind, k unsafe.Pointer) error {
99
case reflect.Int : p.k = rt.Mem2Str(p.m[:native.I64toa(&p.m[0], int64(*(*int)(k)))]) ; return nil
100
case reflect.Int8 : p.k = rt.Mem2Str(p.m[:native.I64toa(&p.m[0], int64(*(*int8)(k)))]) ; return nil
101
case reflect.Int16 : p.k = rt.Mem2Str(p.m[:native.I64toa(&p.m[0], int64(*(*int16)(k)))]) ; return nil
102
case reflect.Int32 : p.k = rt.Mem2Str(p.m[:native.I64toa(&p.m[0], int64(*(*int32)(k)))]) ; return nil
103
case reflect.Int64 : p.k = rt.Mem2Str(p.m[:native.I64toa(&p.m[0], *(*int64)(k))]) ; return nil
104
case reflect.Uint : p.k = rt.Mem2Str(p.m[:native.U64toa(&p.m[0], uint64(*(*uint)(k)))]) ; return nil
105
case reflect.Uint8 : p.k = rt.Mem2Str(p.m[:native.U64toa(&p.m[0], uint64(*(*uint8)(k)))]) ; return nil
106
case reflect.Uint16 : p.k = rt.Mem2Str(p.m[:native.U64toa(&p.m[0], uint64(*(*uint16)(k)))]) ; return nil
107
case reflect.Uint32 : p.k = rt.Mem2Str(p.m[:native.U64toa(&p.m[0], uint64(*(*uint32)(k)))]) ; return nil
108
case reflect.Uint64 : p.k = rt.Mem2Str(p.m[:native.U64toa(&p.m[0], *(*uint64)(k))]) ; return nil
109
case reflect.Uintptr : p.k = rt.Mem2Str(p.m[:native.U64toa(&p.m[0], uint64(*(*uintptr)(k)))]) ; return nil
110
case reflect.Interface : return self.appendInterface(p, t, k)
111
case reflect.Struct, reflect.Ptr : return self.appendConcrete(p, t, k)
112
default : panic("unexpected map key type")
116
func (self *_MapIterator) appendConcrete(p *_MapPair, t *rt.GoType, k unsafe.Pointer) (err error) {
117
// compiler has already checked that the type implements the encoding.MarshalText interface
119
k = *(*unsafe.Pointer)(k)
121
eface := rt.GoEface{Value: k, Type: t}.Pack()
122
out, err := eface.(encoding.TextMarshaler).MarshalText()
126
p.k = rt.Mem2Str(out)
130
func (self *_MapIterator) appendInterface(p *_MapPair, t *rt.GoType, k unsafe.Pointer) (err error) {
131
if len(rt.IfaceType(t).Methods) == 0 {
132
panic("unexpected map key type")
133
} else if p.k, err = asText(k); err == nil {
140
func iteratorStop(p *_MapIterator) {
144
func iteratorNext(p *_MapIterator) {
148
/* check for unordered iteration */
154
/* check for end of iteration */
155
if p.ki >= p.kv.Len {
161
/* update the key-value pair, and increase the pointer */
162
t.K = unsafe.Pointer(&p.at(p.ki).k)
167
func iteratorStart(t *rt.GoMapType, m *rt.GoMap, fv uint64) (*_MapIterator, error) {
169
mapiterinit(t, m, &it.it)
171
/* check for key-sorting, empty map don't need sorting */
172
if m.Count == 0 || (fv & uint64(SortMapKeys)) == 0 {
177
/* pre-allocate space if needed */
178
if m.Count > it.kv.Cap {
179
it.kv = growslice(iteratorPair, it.kv, m.Count)
182
/* dump all the key-value pairs */
183
for ; it.it.K != nil; mapiternext(&it.it) {
184
if err := it.append(t.Key, it.it.K, it.it.V); err != nil {
190
/* sort the keys, map with only 1 item don't need sorting */
191
if it.ki = 1; m.Count > 1 {
192
radixQsort(it.data(), 0, maxDepth(it.kv.Len))
195
/* load the first pair into iterator */
197
it.it.K = unsafe.Pointer(&it.at(0).k)