quickjs-tart

quickjs-based runtime for wallet-core logic
Log | Files | Refs | README | LICENSE

ares_htable_asvp.c (5362B)


      1 /* MIT License
      2  *
      3  * Copyright (c) 2023 Brad House
      4  *
      5  * Permission is hereby granted, free of charge, to any person obtaining a copy
      6  * of this software and associated documentation files (the "Software"), to deal
      7  * in the Software without restriction, including without limitation the rights
      8  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      9  * copies of the Software, and to permit persons to whom the Software is
     10  * furnished to do so, subject to the following conditions:
     11  *
     12  * The above copyright notice and this permission notice (including the next
     13  * paragraph) shall be included in all copies or substantial portions of the
     14  * Software.
     15  *
     16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
     19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
     22  * SOFTWARE.
     23  *
     24  * SPDX-License-Identifier: MIT
     25  */
     26 #include "ares_private.h"
     27 #include "ares_htable.h"
     28 #include "ares_htable_asvp.h"
     29 
     30 struct ares_htable_asvp {
     31   ares_htable_asvp_val_free_t free_val;
     32   ares_htable_t              *hash;
     33 };
     34 
     35 typedef struct {
     36   ares_socket_t       key;
     37   void               *val;
     38   ares_htable_asvp_t *parent;
     39 } ares_htable_asvp_bucket_t;
     40 
     41 void ares_htable_asvp_destroy(ares_htable_asvp_t *htable)
     42 {
     43   if (htable == NULL) {
     44     return;
     45   }
     46 
     47   ares_htable_destroy(htable->hash);
     48   ares_free(htable);
     49 }
     50 
     51 static unsigned int hash_func(const void *key, unsigned int seed)
     52 {
     53   const ares_socket_t *arg = key;
     54   return ares_htable_hash_FNV1a((const unsigned char *)arg, sizeof(*arg), seed);
     55 }
     56 
     57 static const void *bucket_key(const void *bucket)
     58 {
     59   const ares_htable_asvp_bucket_t *arg = bucket;
     60   return &arg->key;
     61 }
     62 
     63 static void bucket_free(void *bucket)
     64 {
     65   ares_htable_asvp_bucket_t *arg = bucket;
     66 
     67   if (arg->parent->free_val) {
     68     arg->parent->free_val(arg->val);
     69   }
     70 
     71   ares_free(arg);
     72 }
     73 
     74 static ares_bool_t key_eq(const void *key1, const void *key2)
     75 {
     76   const ares_socket_t *k1 = key1;
     77   const ares_socket_t *k2 = key2;
     78 
     79   if (*k1 == *k2) {
     80     return ARES_TRUE;
     81   }
     82 
     83   return ARES_FALSE;
     84 }
     85 
     86 ares_htable_asvp_t *
     87   ares_htable_asvp_create(ares_htable_asvp_val_free_t val_free)
     88 {
     89   ares_htable_asvp_t *htable = ares_malloc(sizeof(*htable));
     90   if (htable == NULL) {
     91     goto fail;
     92   }
     93 
     94   htable->hash = ares_htable_create(hash_func, bucket_key, bucket_free, key_eq);
     95   if (htable->hash == NULL) {
     96     goto fail;
     97   }
     98 
     99   htable->free_val = val_free;
    100 
    101   return htable;
    102 
    103 fail:
    104   if (htable) {
    105     ares_htable_destroy(htable->hash);
    106     ares_free(htable);
    107   }
    108   return NULL;
    109 }
    110 
    111 ares_socket_t *ares_htable_asvp_keys(const ares_htable_asvp_t *htable,
    112                                      size_t                   *num)
    113 {
    114   const void   **buckets = NULL;
    115   size_t         cnt     = 0;
    116   ares_socket_t *out     = NULL;
    117   size_t         i;
    118 
    119   if (htable == NULL || num == NULL) {
    120     return NULL; /* LCOV_EXCL_LINE: DefensiveCoding */
    121   }
    122 
    123   *num = 0;
    124 
    125   buckets = ares_htable_all_buckets(htable->hash, &cnt);
    126   if (buckets == NULL || cnt == 0) {
    127     return NULL;
    128   }
    129 
    130   out = ares_malloc_zero(sizeof(*out) * cnt);
    131   if (out == NULL) {
    132     ares_free(buckets); /* LCOV_EXCL_LINE: OutOfMemory */
    133     return NULL;        /* LCOV_EXCL_LINE: OutOfMemory */
    134   }
    135 
    136   for (i = 0; i < cnt; i++) {
    137     out[i] = ((const ares_htable_asvp_bucket_t *)buckets[i])->key;
    138   }
    139 
    140   ares_free(buckets);
    141   *num = cnt;
    142   return out;
    143 }
    144 
    145 ares_bool_t ares_htable_asvp_insert(ares_htable_asvp_t *htable,
    146                                     ares_socket_t key, void *val)
    147 {
    148   ares_htable_asvp_bucket_t *bucket = NULL;
    149 
    150   if (htable == NULL) {
    151     goto fail;
    152   }
    153 
    154   bucket = ares_malloc(sizeof(*bucket));
    155   if (bucket == NULL) {
    156     goto fail; /* LCOV_EXCL_LINE: OutOfMemory */
    157   }
    158 
    159   bucket->parent = htable;
    160   bucket->key    = key;
    161   bucket->val    = val;
    162 
    163   if (!ares_htable_insert(htable->hash, bucket)) {
    164     goto fail; /* LCOV_EXCL_LINE: OutOfMemory */
    165   }
    166 
    167   return ARES_TRUE;
    168 
    169 fail:
    170   if (bucket) {
    171     ares_free(bucket); /* LCOV_EXCL_LINE: OutOfMemory */
    172   }
    173   return ARES_FALSE;
    174 }
    175 
    176 ares_bool_t ares_htable_asvp_get(const ares_htable_asvp_t *htable,
    177                                  ares_socket_t key, void **val)
    178 {
    179   ares_htable_asvp_bucket_t *bucket = NULL;
    180 
    181   if (val) {
    182     *val = NULL;
    183   }
    184 
    185   if (htable == NULL) {
    186     return ARES_FALSE;
    187   }
    188 
    189   bucket = ares_htable_get(htable->hash, &key);
    190   if (bucket == NULL) {
    191     return ARES_FALSE;
    192   }
    193 
    194   if (val) {
    195     *val = bucket->val;
    196   }
    197   return ARES_TRUE;
    198 }
    199 
    200 void *ares_htable_asvp_get_direct(const ares_htable_asvp_t *htable,
    201                                   ares_socket_t             key)
    202 {
    203   void *val = NULL;
    204   ares_htable_asvp_get(htable, key, &val);
    205   return val;
    206 }
    207 
    208 ares_bool_t ares_htable_asvp_remove(ares_htable_asvp_t *htable,
    209                                     ares_socket_t       key)
    210 {
    211   if (htable == NULL) {
    212     return ARES_FALSE;
    213   }
    214 
    215   return ares_htable_remove(htable->hash, &key);
    216 }
    217 
    218 size_t ares_htable_asvp_num_keys(const ares_htable_asvp_t *htable)
    219 {
    220   if (htable == NULL) {
    221     return 0;
    222   }
    223   return ares_htable_num_keys(htable->hash);
    224 }