123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115 |
- /*
- * 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 caching
- import (
- `strings`
- `unsafe`
- `github.com/bytedance/sonic/internal/rt`
- )
- type FieldMap struct {
- N uint64
- b unsafe.Pointer
- m map[string]int
- }
- type FieldEntry struct {
- ID int
- Name string
- Hash uint64
- }
- const (
- FieldMap_N = int64(unsafe.Offsetof(FieldMap{}.N))
- FieldMap_b = int64(unsafe.Offsetof(FieldMap{}.b))
- FieldEntrySize = int64(unsafe.Sizeof(FieldEntry{}))
- )
- func newBucket(n int) unsafe.Pointer {
- v := make([]FieldEntry, n)
- return (*rt.GoSlice)(unsafe.Pointer(&v)).Ptr
- }
- func CreateFieldMap(n int) *FieldMap {
- return &FieldMap {
- N: uint64(n * 2),
- b: newBucket(n * 2), // LoadFactor = 0.5
- m: make(map[string]int, n * 2),
- }
- }
- func (self *FieldMap) At(p uint64) *FieldEntry {
- off := uintptr(p) * uintptr(FieldEntrySize)
- return (*FieldEntry)(unsafe.Pointer(uintptr(self.b) + off))
- }
- // Get searches FieldMap by name. JIT generated assembly does NOT call this
- // function, rather it implements its own version directly in assembly. So
- // we must ensure this function stays in sync with the JIT generated one.
- func (self *FieldMap) Get(name string) int {
- h := StrHash(name)
- p := h % self.N
- s := self.At(p)
- /* find the element;
- * the hash map is never full, so the loop will always terminate */
- for s.Hash != 0 {
- if s.Hash == h && s.Name == name {
- return s.ID
- } else {
- p = (p + 1) % self.N
- s = self.At(p)
- }
- }
- /* not found */
- return -1
- }
- func (self *FieldMap) Set(name string, i int) {
- h := StrHash(name)
- p := h % self.N
- s := self.At(p)
- /* searching for an empty slot;
- * the hash map is never full, so the loop will always terminate */
- for s.Hash != 0 {
- p = (p + 1) % self.N
- s = self.At(p)
- }
- /* set the value */
- s.ID = i
- s.Hash = h
- s.Name = name
- /* add the case-insensitive version, prefer the one with smaller field ID */
- key := strings.ToLower(name)
- if v, ok := self.m[key]; !ok || i < v {
- self.m[key] = i
- }
- }
- func (self *FieldMap) GetCaseInsensitive(name string) int {
- if i, ok := self.m[strings.ToLower(name)]; ok {
- return i
- } else {
- return -1
- }
- }
|