github.com/goshafaq/sonic@v0.0.0-20231026082336-871835fb94c6/internal/encoder/mapiter.go (about)

     1  /*
     2   * Copyright 2021 ByteDance Inc.
     3   *
     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
     7   *
     8   *     http://www.apache.org/licenses/LICENSE-2.0
     9   *
    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.
    15   */
    16  
    17  package encoder
    18  
    19  import (
    20  	"encoding"
    21  	"reflect"
    22  	"sync"
    23  	"unsafe"
    24  
    25  	"github.com/goshafaq/sonic/internal/native"
    26  	"github.com/goshafaq/sonic/internal/rt"
    27  )
    28  
    29  type _MapPair struct {
    30  	k string // when the map key is integer, k is pointed to m
    31  	v unsafe.Pointer
    32  	m [32]byte
    33  }
    34  
    35  type _MapIterator struct {
    36  	it rt.GoMapIterator // must be the first field
    37  	kv rt.GoSlice       // slice of _MapPair
    38  	ki int
    39  }
    40  
    41  var (
    42  	iteratorPool = sync.Pool{}
    43  	iteratorPair = rt.UnpackType(reflect.TypeOf(_MapPair{}))
    44  )
    45  
    46  func init() {
    47  	if unsafe.Offsetof(_MapIterator{}.it) != 0 {
    48  		panic("_MapIterator.it is not the first field")
    49  	}
    50  }
    51  
    52  func newIterator() *_MapIterator {
    53  	if v := iteratorPool.Get(); v == nil {
    54  		return new(_MapIterator)
    55  	} else {
    56  		return resetIterator(v.(*_MapIterator))
    57  	}
    58  }
    59  
    60  func resetIterator(p *_MapIterator) *_MapIterator {
    61  	p.ki = 0
    62  	p.it = rt.GoMapIterator{}
    63  	p.kv.Len = 0
    64  	return p
    65  }
    66  
    67  func (self *_MapIterator) at(i int) *_MapPair {
    68  	return (*_MapPair)(unsafe.Pointer(uintptr(self.kv.Ptr) + uintptr(i)*unsafe.Sizeof(_MapPair{})))
    69  }
    70  
    71  func (self *_MapIterator) add() (p *_MapPair) {
    72  	p = self.at(self.kv.Len)
    73  	self.kv.Len++
    74  	return
    75  }
    76  
    77  func (self *_MapIterator) data() (p []_MapPair) {
    78  	*(*rt.GoSlice)(unsafe.Pointer(&p)) = self.kv
    79  	return
    80  }
    81  
    82  func (self *_MapIterator) append(t *rt.GoType, k unsafe.Pointer, v unsafe.Pointer) (err error) {
    83  	p := self.add()
    84  	p.v = v
    85  
    86  	/* check for strings */
    87  	if tk := t.Kind(); tk != reflect.String {
    88  		return self.appendGeneric(p, t, tk, k)
    89  	}
    90  
    91  	/* fast path for strings */
    92  	p.k = *(*string)(k)
    93  	return nil
    94  }
    95  
    96  func (self *_MapIterator) appendGeneric(p *_MapPair, t *rt.GoType, v reflect.Kind, k unsafe.Pointer) error {
    97  	switch v {
    98  	case reflect.Int:
    99  		p.k = rt.Mem2Str(p.m[:native.I64toa(&p.m[0], int64(*(*int)(k)))])
   100  		return nil
   101  	case reflect.Int8:
   102  		p.k = rt.Mem2Str(p.m[:native.I64toa(&p.m[0], int64(*(*int8)(k)))])
   103  		return nil
   104  	case reflect.Int16:
   105  		p.k = rt.Mem2Str(p.m[:native.I64toa(&p.m[0], int64(*(*int16)(k)))])
   106  		return nil
   107  	case reflect.Int32:
   108  		p.k = rt.Mem2Str(p.m[:native.I64toa(&p.m[0], int64(*(*int32)(k)))])
   109  		return nil
   110  	case reflect.Int64:
   111  		p.k = rt.Mem2Str(p.m[:native.I64toa(&p.m[0], *(*int64)(k))])
   112  		return nil
   113  	case reflect.Uint:
   114  		p.k = rt.Mem2Str(p.m[:native.U64toa(&p.m[0], uint64(*(*uint)(k)))])
   115  		return nil
   116  	case reflect.Uint8:
   117  		p.k = rt.Mem2Str(p.m[:native.U64toa(&p.m[0], uint64(*(*uint8)(k)))])
   118  		return nil
   119  	case reflect.Uint16:
   120  		p.k = rt.Mem2Str(p.m[:native.U64toa(&p.m[0], uint64(*(*uint16)(k)))])
   121  		return nil
   122  	case reflect.Uint32:
   123  		p.k = rt.Mem2Str(p.m[:native.U64toa(&p.m[0], uint64(*(*uint32)(k)))])
   124  		return nil
   125  	case reflect.Uint64:
   126  		p.k = rt.Mem2Str(p.m[:native.U64toa(&p.m[0], *(*uint64)(k))])
   127  		return nil
   128  	case reflect.Uintptr:
   129  		p.k = rt.Mem2Str(p.m[:native.U64toa(&p.m[0], uint64(*(*uintptr)(k)))])
   130  		return nil
   131  	case reflect.Interface:
   132  		return self.appendInterface(p, t, k)
   133  	case reflect.Struct, reflect.Ptr:
   134  		return self.appendConcrete(p, t, k)
   135  	default:
   136  		panic("unexpected map key type")
   137  	}
   138  }
   139  
   140  func (self *_MapIterator) appendConcrete(p *_MapPair, t *rt.GoType, k unsafe.Pointer) (err error) {
   141  	// compiler has already checked that the type implements the encoding.MarshalText interface
   142  	if !t.Indirect() {
   143  		k = *(*unsafe.Pointer)(k)
   144  	}
   145  	eface := rt.GoEface{Value: k, Type: t}.Pack()
   146  	out, err := eface.(encoding.TextMarshaler).MarshalText()
   147  	if err != nil {
   148  		return err
   149  	}
   150  	p.k = rt.Mem2Str(out)
   151  	return
   152  }
   153  
   154  func (self *_MapIterator) appendInterface(p *_MapPair, t *rt.GoType, k unsafe.Pointer) (err error) {
   155  	if len(rt.IfaceType(t).Methods) == 0 {
   156  		panic("unexpected map key type")
   157  	} else if p.k, err = asText(k); err == nil {
   158  		return nil
   159  	} else {
   160  		return
   161  	}
   162  }
   163  
   164  func iteratorStop(p *_MapIterator) {
   165  	iteratorPool.Put(p)
   166  }
   167  
   168  func iteratorNext(p *_MapIterator) {
   169  	i := p.ki
   170  	t := &p.it
   171  
   172  	/* check for unordered iteration */
   173  	if i < 0 {
   174  		mapiternext(t)
   175  		return
   176  	}
   177  
   178  	/* check for end of iteration */
   179  	if p.ki >= p.kv.Len {
   180  		t.K = nil
   181  		t.V = nil
   182  		return
   183  	}
   184  
   185  	/* update the key-value pair, and increase the pointer */
   186  	t.K = unsafe.Pointer(&p.at(p.ki).k)
   187  	t.V = p.at(p.ki).v
   188  	p.ki++
   189  }
   190  
   191  func iteratorStart(t *rt.GoMapType, m *rt.GoMap, fv uint64) (*_MapIterator, error) {
   192  	it := newIterator()
   193  	mapiterinit(t, m, &it.it)
   194  
   195  	/* check for key-sorting, empty map don't need sorting */
   196  	if m.Count == 0 || (fv&uint64(SortMapKeys)) == 0 {
   197  		it.ki = -1
   198  		return it, nil
   199  	}
   200  
   201  	/* pre-allocate space if needed */
   202  	if m.Count > it.kv.Cap {
   203  		it.kv = growslice(iteratorPair, it.kv, m.Count)
   204  	}
   205  
   206  	/* dump all the key-value pairs */
   207  	for ; it.it.K != nil; mapiternext(&it.it) {
   208  		if err := it.append(t.Key, it.it.K, it.it.V); err != nil {
   209  			iteratorStop(it)
   210  			return nil, err
   211  		}
   212  	}
   213  
   214  	/* sort the keys, map with only 1 item don't need sorting */
   215  	if it.ki = 1; m.Count > 1 {
   216  		radixQsort(it.data(), 0, maxDepth(it.kv.Len))
   217  	}
   218  
   219  	/* load the first pair into iterator */
   220  	it.it.V = it.at(0).v
   221  	it.it.K = unsafe.Pointer(&it.at(0).k)
   222  	return it, nil
   223  }