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_setup.h" 27#include "ares.h" 28#include "ares_private.h" 29#include "ares__htable.h" 30#include "ares__htable_szvp.h" 31 32struct ares__htable_szvp { 33 ares__htable_szvp_val_free_t free_val; 34 ares__htable_t *hash; 35}; 36 37typedef struct { 38 size_t key; 39 void *val; 40 ares__htable_szvp_t *parent; 41} ares__htable_szvp_bucket_t; 42 43void ares__htable_szvp_destroy(ares__htable_szvp_t *htable) 44{ 45 if (htable == NULL) { 46 return; 47 } 48 49 ares__htable_destroy(htable->hash); 50 ares_free(htable); 51} 52 53static unsigned int hash_func(const void *key, unsigned int seed) 54{ 55 const size_t *arg = key; 56 return ares__htable_hash_FNV1a((const unsigned char *)arg, sizeof(*arg), 57 seed); 58} 59 60static const void *bucket_key(const void *bucket) 61{ 62 const ares__htable_szvp_bucket_t *arg = bucket; 63 return &arg->key; 64} 65 66static void bucket_free(void *bucket) 67{ 68 ares__htable_szvp_bucket_t *arg = bucket; 69 70 if (arg->parent->free_val) { 71 arg->parent->free_val(arg->val); 72 } 73 74 ares_free(arg); 75} 76 77static ares_bool_t key_eq(const void *key1, const void *key2) 78{ 79 const size_t *k1 = key1; 80 const size_t *k2 = key2; 81 82 if (*k1 == *k2) { 83 return ARES_TRUE; 84 } 85 86 return ARES_FALSE; 87} 88 89ares__htable_szvp_t * 90 ares__htable_szvp_create(ares__htable_szvp_val_free_t val_free) 91{ 92 ares__htable_szvp_t *htable = ares_malloc(sizeof(*htable)); 93 if (htable == NULL) { 94 goto fail; 95 } 96 97 htable->hash = 98 ares__htable_create(hash_func, bucket_key, bucket_free, key_eq); 99 if (htable->hash == NULL) { 100 goto fail; 101 } 102 103 htable->free_val = val_free; 104 105 return htable; 106 107fail: 108 if (htable) { 109 ares__htable_destroy(htable->hash); 110 ares_free(htable); 111 } 112 return NULL; 113} 114 115ares_bool_t ares__htable_szvp_insert(ares__htable_szvp_t *htable, size_t key, 116 void *val) 117{ 118 ares__htable_szvp_bucket_t *bucket = NULL; 119 120 if (htable == NULL) { 121 goto fail; 122 } 123 124 bucket = ares_malloc(sizeof(*bucket)); 125 if (bucket == NULL) { 126 goto fail; 127 } 128 129 bucket->parent = htable; 130 bucket->key = key; 131 bucket->val = val; 132 133 if (!ares__htable_insert(htable->hash, bucket)) { 134 goto fail; 135 } 136 137 return ARES_TRUE; 138 139fail: 140 if (bucket) { 141 ares_free(bucket); 142 } 143 return ARES_FALSE; 144} 145 146ares_bool_t ares__htable_szvp_get(const ares__htable_szvp_t *htable, size_t key, 147 void **val) 148{ 149 ares__htable_szvp_bucket_t *bucket = NULL; 150 151 if (val) { 152 *val = NULL; 153 } 154 155 if (htable == NULL) { 156 return ARES_FALSE; 157 } 158 159 bucket = ares__htable_get(htable->hash, &key); 160 if (bucket == NULL) { 161 return ARES_FALSE; 162 } 163 164 if (val) { 165 *val = bucket->val; 166 } 167 return ARES_TRUE; 168} 169 170void *ares__htable_szvp_get_direct(const ares__htable_szvp_t *htable, 171 size_t key) 172{ 173 void *val = NULL; 174 ares__htable_szvp_get(htable, key, &val); 175 return val; 176} 177 178ares_bool_t ares__htable_szvp_remove(ares__htable_szvp_t *htable, size_t key) 179{ 180 if (htable == NULL) { 181 return ARES_FALSE; 182 } 183 184 return ares__htable_remove(htable->hash, &key); 185} 186 187size_t ares__htable_szvp_num_keys(const ares__htable_szvp_t *htable) 188{ 189 if (htable == NULL) { 190 return 0; 191 } 192 return ares__htable_num_keys(htable->hash); 193} 194