quickjs-tart

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

ares_htable_strvp.c (5001B)


      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_strvp.h"
     29 
     30 struct ares_htable_strvp {
     31   ares_htable_strvp_val_free_t free_val;
     32   ares_htable_t               *hash;
     33 };
     34 
     35 typedef struct {
     36   char                *key;
     37   void                *val;
     38   ares_htable_strvp_t *parent;
     39 } ares_htable_strvp_bucket_t;
     40 
     41 void ares_htable_strvp_destroy(ares_htable_strvp_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 char *arg = key;
     54   return ares_htable_hash_FNV1a_casecmp((const unsigned char *)arg,
     55                                         ares_strlen(arg), seed);
     56 }
     57 
     58 static const void *bucket_key(const void *bucket)
     59 {
     60   const ares_htable_strvp_bucket_t *arg = bucket;
     61   return arg->key;
     62 }
     63 
     64 static void bucket_free(void *bucket)
     65 {
     66   ares_htable_strvp_bucket_t *arg = bucket;
     67 
     68   if (arg->parent->free_val) {
     69     arg->parent->free_val(arg->val);
     70   }
     71   ares_free(arg->key);
     72   ares_free(arg);
     73 }
     74 
     75 static ares_bool_t key_eq(const void *key1, const void *key2)
     76 {
     77   return ares_strcaseeq(key1, key2);
     78 }
     79 
     80 ares_htable_strvp_t *
     81   ares_htable_strvp_create(ares_htable_strvp_val_free_t val_free)
     82 {
     83   ares_htable_strvp_t *htable = ares_malloc(sizeof(*htable));
     84   if (htable == NULL) {
     85     goto fail;
     86   }
     87 
     88   htable->hash = ares_htable_create(hash_func, bucket_key, bucket_free, key_eq);
     89   if (htable->hash == NULL) {
     90     goto fail;
     91   }
     92 
     93   htable->free_val = val_free;
     94 
     95   return htable;
     96 
     97 fail:
     98   if (htable) {
     99     ares_htable_destroy(htable->hash);
    100     ares_free(htable);
    101   }
    102   return NULL;
    103 }
    104 
    105 ares_bool_t ares_htable_strvp_insert(ares_htable_strvp_t *htable,
    106                                      const char *key, void *val)
    107 {
    108   ares_htable_strvp_bucket_t *bucket = NULL;
    109 
    110   if (htable == NULL || key == NULL) {
    111     goto fail;
    112   }
    113 
    114   bucket = ares_malloc(sizeof(*bucket));
    115   if (bucket == NULL) {
    116     goto fail;
    117   }
    118 
    119   bucket->parent = htable;
    120   bucket->key    = ares_strdup(key);
    121   if (bucket->key == NULL) {
    122     goto fail;
    123   }
    124   bucket->val = val;
    125 
    126   if (!ares_htable_insert(htable->hash, bucket)) {
    127     goto fail;
    128   }
    129 
    130   return ARES_TRUE;
    131 
    132 fail:
    133   if (bucket) {
    134     ares_free(bucket->key);
    135     ares_free(bucket);
    136   }
    137   return ARES_FALSE;
    138 }
    139 
    140 ares_bool_t ares_htable_strvp_get(const ares_htable_strvp_t *htable,
    141                                   const char *key, void **val)
    142 {
    143   ares_htable_strvp_bucket_t *bucket = NULL;
    144 
    145   if (val) {
    146     *val = NULL;
    147   }
    148 
    149   if (htable == NULL || key == NULL) {
    150     return ARES_FALSE;
    151   }
    152 
    153   bucket = ares_htable_get(htable->hash, key);
    154   if (bucket == NULL) {
    155     return ARES_FALSE;
    156   }
    157 
    158   if (val) {
    159     *val = bucket->val;
    160   }
    161   return ARES_TRUE;
    162 }
    163 
    164 void *ares_htable_strvp_get_direct(const ares_htable_strvp_t *htable,
    165                                    const char                *key)
    166 {
    167   void *val = NULL;
    168   ares_htable_strvp_get(htable, key, &val);
    169   return val;
    170 }
    171 
    172 ares_bool_t ares_htable_strvp_remove(ares_htable_strvp_t *htable,
    173                                      const char          *key)
    174 {
    175   if (htable == NULL) {
    176     return ARES_FALSE;
    177   }
    178 
    179   return ares_htable_remove(htable->hash, key);
    180 }
    181 
    182 void *ares_htable_strvp_claim(ares_htable_strvp_t *htable, const char *key)
    183 {
    184   ares_htable_strvp_bucket_t *bucket = NULL;
    185   void                       *val;
    186 
    187   if (htable == NULL || key == NULL) {
    188     return NULL;
    189   }
    190 
    191   bucket = ares_htable_get(htable->hash, key);
    192   if (bucket == NULL) {
    193     return NULL;
    194   }
    195 
    196   /* Unassociate value from bucket */
    197   val         = bucket->val;
    198   bucket->val = NULL;
    199 
    200   ares_htable_strvp_remove(htable, key);
    201   return val;
    202 }
    203 
    204 size_t ares_htable_strvp_num_keys(const ares_htable_strvp_t *htable)
    205 {
    206   if (htable == NULL) {
    207     return 0;
    208   }
    209   return ares_htable_num_keys(htable->hash);
    210 }