mirror of
https://github.com/superseriousbusiness/gotosocial.git
synced 2025-01-23 14:50:21 +00:00
4d423102c1
Bumps [github.com/gin-contrib/gzip](https://github.com/gin-contrib/gzip) from 1.0.1 to 1.1.0. - [Release notes](https://github.com/gin-contrib/gzip/releases) - [Changelog](https://github.com/gin-contrib/gzip/blob/master/.goreleaser.yaml) - [Commits](https://github.com/gin-contrib/gzip/compare/v1.0.1...v1.1.0) --- updated-dependencies: - dependency-name: github.com/gin-contrib/gzip dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
207 lines
6.2 KiB
Go
207 lines
6.2 KiB
Go
/*
|
|
* 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
|
|
|
|
/* check for strings */
|
|
if tk := t.Kind(); tk != reflect.String {
|
|
return self.appendGeneric(p, t, tk, k)
|
|
}
|
|
|
|
/* fast path for strings */
|
|
p.k = *(*string)(k)
|
|
return nil
|
|
}
|
|
|
|
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.Interface : return self.appendInterface(p, t, k)
|
|
case reflect.Struct, reflect.Ptr : return self.appendConcrete(p, t, k)
|
|
default : panic("unexpected map key type")
|
|
}
|
|
}
|
|
|
|
func (self *MapIterator) appendConcrete(p *_MapPair, t *rt.GoType, k unsafe.Pointer) (err error) {
|
|
// compiler has already checked that the type implements the encoding.MarshalText interface
|
|
if !t.Indirect() {
|
|
k = *(*unsafe.Pointer)(k)
|
|
}
|
|
eface := rt.GoEface{Value: k, Type: t}.Pack()
|
|
out, err := eface.(encoding.TextMarshaler).MarshalText()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
p.k = rt.Mem2Str(out)
|
|
return
|
|
}
|
|
|
|
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")
|
|
} else if p.k, err = asText(k); err == nil {
|
|
return nil
|
|
} else {
|
|
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 *rt.GoMap, fv uint64) (*MapIterator, error) {
|
|
it := newIterator()
|
|
rt.Mapiterinit(t, m, &it.It)
|
|
|
|
/* check for key-sorting, empty map don't need sorting */
|
|
if m.Count == 0 || (fv & (1<<BitSortMapKeys)) == 0 {
|
|
it.ki = -1
|
|
return it, nil
|
|
}
|
|
|
|
/* pre-allocate space if needed */
|
|
if m.Count > it.kv.Cap {
|
|
it.kv = rt.GrowSlice(iteratorPair, it.kv, m.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; m.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
|
|
}
|