github.com/cloudwego/dynamicgo@v0.2.6-0.20240519101509-707f41b6b834/native/map.c (about)

     1  /**
     2   * Copyright 2023 CloudWeGo Authors.
     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  #include "native.h"
    18  #include "memops.h"
    19  #include "map.h"
    20  #include "test/xprintf.h"
    21  
    22  uint32_t hash_DJB32(const GoString str)
    23  {
    24      uint32_t hash = 5381ul;
    25      for (int i = 0; i < str.len; i++)
    26      {
    27          hash = ((hash << 5) + hash + (uint32_t)str.buf[i]);
    28      }
    29      return hash;
    30  }
    31  
    32  void *hm_get(const HashMap *self, const GoString *key)
    33  {
    34      uint32_t h = hash_DJB32(*key);
    35      uint32_t p = h % self->N;
    36      Entry s = self->b[p];
    37  
    38      while (s.hash != 0)
    39      {
    40          if (s.hash == h && s.key.len == key->len && memeq(key->buf, s.key.buf, key->len))
    41          {
    42              // xprintf("s.key:%s, s.val:%x\n", s.key.buf, s.val);
    43              return s.val;
    44          }
    45          else
    46          {
    47              p = (p + 1) % self->N;
    48              s = self->b[p];
    49          }
    50      }
    51      return NULL;
    52  }
    53  
    54  void hm_set(HashMap *self, const GoString *key, void *val)
    55  {
    56      uint32_t h = hash_DJB32(*key);
    57      uint32_t p = h % self->N;
    58      Entry *s = &self->b[p];
    59  
    60      while (s->hash != 0)
    61      {
    62          p = (p + 1) % self->N;
    63          s = &self->b[p];
    64      }
    65  
    66      // xprintf("h:%d, p:%d, key:%s, val:%x\n", h, p, key, val);
    67      s->val = val;
    68      s->hash = h;
    69      s->key = *key;
    70      self->c++;
    71  }
    72  
    73  const size_t SIZE_SIZE_T = sizeof(size_t);
    74  const size_t SIZE_TRIE_NODE = sizeof(TrieNode);
    75  const size_t SIZE_PAIR = sizeof(Pair);
    76  
    77  uint8_t ascii2int(const unsigned char c)
    78  {
    79      if (c < CHAR_POINT)
    80      {
    81          return (uint8_t)(255 + c - CHAR_POINT);
    82      }
    83      return (uint8_t)(c - CHAR_POINT);
    84  }
    85  
    86  void *trie_get(const TrieTree *self, const GoString *key)
    87  {
    88      // xprintf("[trie_get] key:%s\n", key);
    89      if (key->len == 0)
    90      {
    91          return self->empty;
    92      }
    93  
    94      size_t l = key->len - 1;
    95      GoSlice fs = self->node.index;
    96      GoSlice ls = *self->node.leaves;
    97  
    98      for (int s = 0; s < self->positions.len; s++)
    99      {
   100          size_t i = *(size_t *)(self->positions.buf + s * SIZE_SIZE_T);
   101          // xprintf("[trie_get] l:%d, position:%d\n", l, i);
   102          if (i > l)
   103          {
   104              i = l;
   105          }
   106          uint8_t j = ascii2int(key->buf[i]);
   107          if (j > fs.len)
   108          {
   109              return NULL;
   110          }
   111          // xprintf("[trie_get] j:%d, fs.len:%d\n", j, fs.len);
   112          TrieNode *fp = (TrieNode *)(fs.buf + j * SIZE_TRIE_NODE);
   113          if (fp->leaves == NULL)
   114          {
   115              return NULL;
   116          }
   117          fs = fp->index;
   118          ls = *fp->leaves;
   119          // xprintf("[trie_get] fp->leaves[0]:%s\n", &((Pair *)(ls.buf))->key);
   120      }
   121      // xprintf("[trie_get] ls.len:%d\n", l, ls.len);
   122  
   123      for (int i = 0; i < ls.len; i++)
   124      {
   125          Pair *v = (Pair *)(ls.buf + i * SIZE_PAIR);
   126          if (key->len == v->key.len && memeq(key->buf, v->key.buf, key->len))
   127          {
   128              return v->val;
   129          }
   130      }
   131      return NULL;
   132  }
   133  
   134  bool bm_is_set(ReqBitMap b, tid id)
   135  {
   136      uint64_t v = b.buf[id / BSIZE_INT64];
   137      return (v & (1ull << (id % BSIZE_INT64))) != 0;
   138  }
   139  
   140  void bm_set_req(ReqBitMap b, tid id, req_em req)
   141  {
   142      uint64_t *p = &b.buf[id / BSIZE_INT64];
   143      switch (req)
   144      {
   145      case REQ_DEFAULT:
   146      case REQ_REQUIRED:
   147          *p |= (uint64_t)(1ull << (id % BSIZE_INT64));
   148          break;
   149      case REQ_OPTIONAL:
   150          *p &= ~(uint64_t)(1ull << (id % BSIZE_INT64));
   151          break;
   152      default:
   153          break;
   154      }
   155  }