chore: migrate to gitea
This commit is contained in:
285
vendor/github.com/bytedance/sonic/internal/encoder/alg/mapiter.go
generated
vendored
Normal file
285
vendor/github.com/bytedance/sonic/internal/encoder/alg/mapiter.go
generated
vendored
Normal file
@@ -0,0 +1,285 @@
|
||||
/*
|
||||
* Copyright 2021 ByteDance Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package alg
|
||||
|
||||
import (
|
||||
"encoding"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"sync"
|
||||
"unsafe"
|
||||
|
||||
"github.com/bytedance/sonic/internal/encoder/vars"
|
||||
"github.com/bytedance/sonic/internal/rt"
|
||||
)
|
||||
|
||||
type _MapPair struct {
|
||||
k string // when the map key is integer, k is pointed to m
|
||||
v unsafe.Pointer
|
||||
m [32]byte
|
||||
}
|
||||
|
||||
type MapIterator struct {
|
||||
It rt.GoMapIterator // must be the first field
|
||||
kv rt.GoSlice // slice of _MapPair
|
||||
ki int
|
||||
}
|
||||
|
||||
var (
|
||||
iteratorPool = sync.Pool{}
|
||||
iteratorPair = rt.UnpackType(reflect.TypeOf(_MapPair{}))
|
||||
)
|
||||
|
||||
func init() {
|
||||
if unsafe.Offsetof(MapIterator{}.It) != 0 {
|
||||
panic("_MapIterator.it is not the first field")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func newIterator() *MapIterator {
|
||||
if v := iteratorPool.Get(); v == nil {
|
||||
return new(MapIterator)
|
||||
} else {
|
||||
return resetIterator(v.(*MapIterator))
|
||||
}
|
||||
}
|
||||
|
||||
func resetIterator(p *MapIterator) *MapIterator {
|
||||
p.ki = 0
|
||||
p.It = rt.GoMapIterator{}
|
||||
p.kv.Len = 0
|
||||
return p
|
||||
}
|
||||
|
||||
func (self *MapIterator) at(i int) *_MapPair {
|
||||
return (*_MapPair)(unsafe.Pointer(uintptr(self.kv.Ptr) + uintptr(i) * unsafe.Sizeof(_MapPair{})))
|
||||
}
|
||||
|
||||
func (self *MapIterator) add() (p *_MapPair) {
|
||||
p = self.at(self.kv.Len)
|
||||
self.kv.Len++
|
||||
return
|
||||
}
|
||||
|
||||
func (self *MapIterator) data() (p []_MapPair) {
|
||||
*(*rt.GoSlice)(unsafe.Pointer(&p)) = self.kv
|
||||
return
|
||||
}
|
||||
|
||||
func (self *MapIterator) append(t *rt.GoType, k unsafe.Pointer, v unsafe.Pointer) (err error) {
|
||||
p := self.add()
|
||||
p.v = v
|
||||
tk := t.Kind()
|
||||
|
||||
// followed as `encoding/json/emcode.go:resolveKeyName
|
||||
if tk == reflect.String {
|
||||
p.k = *(*string)(k)
|
||||
return nil
|
||||
}
|
||||
|
||||
// check if the key implements the encoding.TextMarshaler interface
|
||||
if t.Pack().Implements(vars.EncodingTextMarshalerType) {
|
||||
if tk != reflect.Interface {
|
||||
return self.appendConcrete(p, t, k)
|
||||
} else {
|
||||
return self.appendInterface(p, t, k)
|
||||
}
|
||||
}
|
||||
|
||||
return self.appendGeneric(p, t, tk, k)
|
||||
}
|
||||
|
||||
func (self *MapIterator) appendGeneric(p *_MapPair, t *rt.GoType, v reflect.Kind, k unsafe.Pointer) error {
|
||||
switch v {
|
||||
case reflect.Int : p.k = rt.Mem2Str(strconv.AppendInt(p.m[:0], int64(*(*int)(k)), 10)) ; return nil
|
||||
case reflect.Int8 : p.k = rt.Mem2Str(strconv.AppendInt(p.m[:0], int64(*(*int8)(k)), 10)) ; return nil
|
||||
case reflect.Int16 : p.k = rt.Mem2Str(strconv.AppendInt(p.m[:0], int64(*(*int16)(k)), 10)) ; return nil
|
||||
case reflect.Int32 : p.k = rt.Mem2Str(strconv.AppendInt(p.m[:0], int64(*(*int32)(k)), 10)) ; return nil
|
||||
case reflect.Int64 : p.k = rt.Mem2Str(strconv.AppendInt(p.m[:0], int64(*(*int64)(k)), 10)) ; return nil
|
||||
case reflect.Uint : p.k = rt.Mem2Str(strconv.AppendUint(p.m[:0], uint64(*(*uint)(k)), 10)) ; return nil
|
||||
case reflect.Uint8 : p.k = rt.Mem2Str(strconv.AppendUint(p.m[:0], uint64(*(*uint8)(k)), 10)) ; return nil
|
||||
case reflect.Uint16 : p.k = rt.Mem2Str(strconv.AppendUint(p.m[:0], uint64(*(*uint16)(k)), 10)) ; return nil
|
||||
case reflect.Uint32 : p.k = rt.Mem2Str(strconv.AppendUint(p.m[:0], uint64(*(*uint32)(k)), 10)) ; return nil
|
||||
case reflect.Uint64 : p.k = rt.Mem2Str(strconv.AppendUint(p.m[:0], uint64(*(*uint64)(k)), 10)) ; return nil
|
||||
case reflect.Uintptr : p.k = rt.Mem2Str(strconv.AppendUint(p.m[:0], uint64(*(*uintptr)(k)), 10)) ; return nil
|
||||
case reflect.Bool : if *(*bool)(k) { p.k = "true" } else { p.k = "false" }; return nil
|
||||
default : return vars.Error_type(t.Pack())
|
||||
}
|
||||
}
|
||||
|
||||
func (self *MapIterator) appendConcrete(p *_MapPair, t *rt.GoType, k unsafe.Pointer) error {
|
||||
// compiler has already checked that the type implements the encoding.MarshalText interface
|
||||
if !t.Indirect() {
|
||||
k = *(*unsafe.Pointer)(k)
|
||||
}
|
||||
|
||||
// check the TextMarshaler interface
|
||||
eface := rt.GoEface{Value: k, Type: t}.Pack()
|
||||
e, ok := eface.(encoding.TextMarshaler)
|
||||
if !ok {
|
||||
return vars.Error_type(t.Pack())
|
||||
}
|
||||
|
||||
// check for nil pointer
|
||||
if t.Kind() == reflect.Ptr && k == nil {
|
||||
p.k = ""
|
||||
return nil
|
||||
}
|
||||
|
||||
out, err := e.MarshalText()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
p.k = rt.Mem2Str(out)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *MapIterator) appendInterface(p *_MapPair, t *rt.GoType, k unsafe.Pointer) (err error) {
|
||||
if len(rt.IfaceType(t).Methods) == 0 {
|
||||
panic("unexpected map key type")
|
||||
}
|
||||
p.k, err = asText(k)
|
||||
return
|
||||
}
|
||||
|
||||
func IteratorStop(p *MapIterator) {
|
||||
iteratorPool.Put(p)
|
||||
}
|
||||
|
||||
func IteratorNext(p *MapIterator) {
|
||||
i := p.ki
|
||||
t := &p.It
|
||||
|
||||
/* check for unordered iteration */
|
||||
if i < 0 {
|
||||
rt.Mapiternext(t)
|
||||
return
|
||||
}
|
||||
|
||||
/* check for end of iteration */
|
||||
if p.ki >= p.kv.Len {
|
||||
t.K = nil
|
||||
t.V = nil
|
||||
return
|
||||
}
|
||||
|
||||
/* update the key-value pair, and increase the pointer */
|
||||
t.K = unsafe.Pointer(&p.at(p.ki).k)
|
||||
t.V = p.at(p.ki).v
|
||||
p.ki++
|
||||
}
|
||||
|
||||
func IteratorStart(t *rt.GoMapType, m unsafe.Pointer, fv uint64) (*MapIterator, error) {
|
||||
it := newIterator()
|
||||
rt.Mapiterinit(t, m, &it.It)
|
||||
count := rt.Maplen(m)
|
||||
|
||||
/* check for key-sorting, empty map don't need sorting */
|
||||
if count == 0 || (fv & (1<<BitSortMapKeys)) == 0 {
|
||||
it.ki = -1
|
||||
return it, nil
|
||||
}
|
||||
|
||||
/* pre-allocate space if needed */
|
||||
if count > it.kv.Cap {
|
||||
it.kv = rt.GrowSlice(iteratorPair, it.kv, count)
|
||||
}
|
||||
|
||||
/* dump all the key-value pairs */
|
||||
for ; it.It.K != nil; rt.Mapiternext(&it.It) {
|
||||
if err := it.append(t.Key, it.It.K, it.It.V); err != nil {
|
||||
IteratorStop(it)
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
/* sort the keys, map with only 1 item don't need sorting */
|
||||
if it.ki = 1; count > 1 {
|
||||
radixQsort(it.data(), 0, maxDepth(it.kv.Len))
|
||||
}
|
||||
|
||||
/* load the first pair into iterator */
|
||||
it.It.V = it.at(0).v
|
||||
it.It.K = unsafe.Pointer(&it.at(0).k)
|
||||
return it, nil
|
||||
}
|
||||
|
||||
func asText(v unsafe.Pointer) (string, error) {
|
||||
text := rt.AssertI2I(rt.UnpackType(vars.EncodingTextMarshalerType), *(*rt.GoIface)(v))
|
||||
r, e := (*(*encoding.TextMarshaler)(unsafe.Pointer(&text))).MarshalText()
|
||||
return rt.Mem2Str(r), e
|
||||
}
|
||||
|
||||
func IsValidNumber(s string) bool {
|
||||
// This function implements the JSON numbers grammar.
|
||||
// See https://tools.ietf.org/html/rfc7159#section-6
|
||||
// and https://www.json.org/img/number.png
|
||||
|
||||
if s == "" {
|
||||
return false
|
||||
}
|
||||
|
||||
// Optional -
|
||||
if s[0] == '-' {
|
||||
s = s[1:]
|
||||
if s == "" {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// Digits
|
||||
switch {
|
||||
default:
|
||||
return false
|
||||
|
||||
case s[0] == '0':
|
||||
s = s[1:]
|
||||
|
||||
case '1' <= s[0] && s[0] <= '9':
|
||||
s = s[1:]
|
||||
for len(s) > 0 && '0' <= s[0] && s[0] <= '9' {
|
||||
s = s[1:]
|
||||
}
|
||||
}
|
||||
|
||||
// . followed by 1 or more digits.
|
||||
if len(s) >= 2 && s[0] == '.' && '0' <= s[1] && s[1] <= '9' {
|
||||
s = s[2:]
|
||||
for len(s) > 0 && '0' <= s[0] && s[0] <= '9' {
|
||||
s = s[1:]
|
||||
}
|
||||
}
|
||||
|
||||
// e or E followed by an optional - or + and
|
||||
// 1 or more digits.
|
||||
if len(s) >= 2 && (s[0] == 'e' || s[0] == 'E') {
|
||||
s = s[1:]
|
||||
if s[0] == '+' || s[0] == '-' {
|
||||
s = s[1:]
|
||||
if s == "" {
|
||||
return false
|
||||
}
|
||||
}
|
||||
for len(s) > 0 && '0' <= s[0] && s[0] <= '9' {
|
||||
s = s[1:]
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure we are at the end.
|
||||
return s == ""
|
||||
}
|
||||
Reference in New Issue
Block a user