gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

fcache.go (2894B)


      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 caching
     18 
     19 import (
     20     `strings`
     21     `unsafe`
     22 
     23     `github.com/bytedance/sonic/internal/rt`
     24 )
     25 
     26 type FieldMap struct {
     27     N uint64
     28     b unsafe.Pointer
     29     m map[string]int
     30 }
     31 
     32 type FieldEntry struct {
     33     ID   int
     34     Name string
     35     Hash uint64
     36 }
     37 
     38 const (
     39     FieldMap_N     = int64(unsafe.Offsetof(FieldMap{}.N))
     40     FieldMap_b     = int64(unsafe.Offsetof(FieldMap{}.b))
     41 	FieldEntrySize = int64(unsafe.Sizeof(FieldEntry{}))
     42 )
     43 
     44 func newBucket(n int) unsafe.Pointer {
     45     v := make([]FieldEntry, n)
     46     return (*rt.GoSlice)(unsafe.Pointer(&v)).Ptr
     47 }
     48 
     49 func CreateFieldMap(n int) *FieldMap {
     50     return &FieldMap {
     51         N: uint64(n * 2),
     52         b: newBucket(n * 2),    // LoadFactor = 0.5
     53         m: make(map[string]int, n * 2),
     54     }
     55 }
     56 
     57 func (self *FieldMap) At(p uint64) *FieldEntry {
     58     off := uintptr(p) * uintptr(FieldEntrySize)
     59     return (*FieldEntry)(unsafe.Pointer(uintptr(self.b) + off))
     60 }
     61 
     62 // Get searches FieldMap by name. JIT generated assembly does NOT call this
     63 // function, rather it implements its own version directly in assembly. So
     64 // we must ensure this function stays in sync with the JIT generated one.
     65 func (self *FieldMap) Get(name string) int {
     66     h := StrHash(name)
     67     p := h % self.N
     68     s := self.At(p)
     69 
     70     /* find the element;
     71      * the hash map is never full, so the loop will always terminate */
     72     for s.Hash != 0 {
     73         if s.Hash == h && s.Name == name {
     74             return s.ID
     75         } else {
     76             p = (p + 1) % self.N
     77             s = self.At(p)
     78         }
     79     }
     80 
     81     /* not found */
     82     return -1
     83 }
     84 
     85 func (self *FieldMap) Set(name string, i int) {
     86     h := StrHash(name)
     87     p := h % self.N
     88     s := self.At(p)
     89 
     90     /* searching for an empty slot;
     91      * the hash map is never full, so the loop will always terminate */
     92     for s.Hash != 0 {
     93         p = (p + 1) % self.N
     94         s = self.At(p)
     95     }
     96 
     97     /* set the value */
     98     s.ID   = i
     99     s.Hash = h
    100     s.Name = name
    101 
    102     /* add the case-insensitive version, prefer the one with smaller field ID */
    103     key := strings.ToLower(name)
    104     if v, ok := self.m[key]; !ok || i < v {
    105         self.m[key] = i
    106     }
    107 }
    108 
    109 func (self *FieldMap) GetCaseInsensitive(name string) int {
    110     if i, ok := self.m[strings.ToLower(name)]; ok {
    111         return i
    112     } else {
    113         return -1
    114     }
    115 }